Spring中的AOP動(dòng)態(tài)代理源碼詳解
一、Spring啟動(dòng)流程再分析
配置類(lèi),開(kāi)啟 AOP 的注解 @EnableAspectJAutoProxy
@Configuration @ComponentScan("com.scorpios") @EnableAspectJAutoProxy public class AppConfig { }
切面類(lèi)
@Aspect @Component public class AspectJScorpios { @Pointcut("execution(* com.scorpios.service..*.*(..))") public void pointCut(){ } @Before("pointCut()") public void before(){ System.out.println(" proxy before ... "); } }
啟動(dòng)類(lèi)
public static void main( String[] args ) { AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(); ac.register(AppConfig.class); ac.refresh(); XService xService = (XService) ac.getBean("XService"); xService.print(); }
1. 處理Import過(guò)程
對(duì)于 Import 的處理過(guò)程,可以看一下源碼分析第四篇,包掃描中處理 @Import 注解部分。
@EnableAspectJAutoProxy 注解源碼,使用 @Import 注解,向 Spring 容器中導(dǎo)入 AspectJAutoProxyRegistrar 類(lèi),而 AspectJAutoProxyRegistrar 類(lèi)實(shí)現(xiàn) ImportBeanDefinitionRegistrar 接口。
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(AspectJAutoProxyRegistrar.class) public @interface EnableAspectJAutoProxy { boolean proxyTargetClass() default false; boolean exposeProxy() default false; }
AOP 的原理和 Mybatis 的原理一樣,都是通過(guò)實(shí)現(xiàn) ImportBeanDefinitionRegistrar 接口, Mybatis 的實(shí)現(xiàn)類(lèi)是 MapperScannerRegistrar ,而 AOP 的實(shí)現(xiàn)類(lèi)是 AspectJAutoProxyRegistrar 。
// Mybatis
class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar
// AOP
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar
2. 執(zhí)行Import導(dǎo)入類(lèi)
在 parser.parse(candidates); 這行代碼里完成了對(duì) @Import 注解的導(dǎo)入工作,并對(duì)實(shí)現(xiàn) ImportBeanDefinitionRegistrar 接口的類(lèi)完成了實(shí)例化,并把已經(jīng)創(chuàng)建好的實(shí)列放到了 ConfigurationClass 類(lèi)的屬性 importBeanDefinitionRegistrars 中,可以看下面斷點(diǎn)圖。
this.reader.loadBeanDefinitions() 這個(gè)方法中完成了對(duì) ImportBeanDefinitionRegistrar 接口方法的調(diào)用。
下面就來(lái)看一下 AspectJAutoProxyRegistrar 類(lèi)中實(shí)現(xiàn) ImportBeanDefinitionRegistrar 接口的方法了。
AOP 的入口就在這里?。。?!
二、AOP源碼分析
1. AspectJAutoProxyRegistrar類(lèi)
來(lái)看一下 AspectJAutoProxyRegistrar 類(lèi)中實(shí)現(xiàn) ImportBeanDefinitionRegistrar 接口方法。
該方法的作用就是往 Spring 容器中添加一個(gè) BeanDefinition , beanName 為 org.springframework.aop.config.internalAutoProxyCreator 。
beanClass 為 AnnotationAwareAspectJAutoProxyCreator.class 。
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions( AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { // 核心方法 AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry); AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class); if (enableAspectJAutoProxy != null) { if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); } if (enableAspectJAutoProxy.getBoolean("exposeProxy")) { AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry); } } } }
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) { return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null); } public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary( BeanDefinitionRegistry registry, @Nullable Object source) { return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source); } private static BeanDefinition registerOrEscalateApcAsRequired( Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) { if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); if (!cls.getName().equals(apcDefinition.getBeanClassName())) { int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName()); int requiredPriority = findPriorityForClass(cls); if (currentPriority < requiredPriority) { apcDefinition.setBeanClassName(cls.getName()); } } return null; } // 此處的的beanClass為AnnotationAwareAspectJAutoProxyCreator.class RootBeanDefinition beanDefinition = new RootBeanDefinition(cls); beanDefinition.setSource(source); beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE); beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); // 往beanDefinitionMap中注冊(cè)一個(gè)beanName為org.springframework.aop.config.internalAutoProxyCreator的BeanDefinition registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition); return beanDefinition; }
2. internalAutoProxyCreator類(lèi)
再觀察一下 internalAutoProxyCreator
,它的實(shí)現(xiàn)類(lèi)是 org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
經(jīng)過(guò) refresh() 方法中的 registerBeanPostProcessors() 方法, BeanPostProcessor 就已經(jīng)實(shí)例化了,并且添加到了 beanFactory 工廠中的 beanPostProcessors 屬性中。
3. BeanPostProcessor方法執(zhí)行
我們要來(lái)看一下 BeanPostProcessor 的執(zhí)行時(shí)機(jī),在 populateBean() 屬性賦值之后的 initializeBean() 方法中,進(jìn)行了 Bean后置處理器 方法的調(diào)用。
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) { // 權(quán)限檢查 if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { // 執(zhí)行setBeanName/setBeanFactory賦值 invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { // 調(diào)用BeanPostProcessor接口中的postProcessBeforeInitialization()方法 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { // 執(zhí)行自定義的init-method方法 invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { // 拋異常代碼略 } if (mbd == null || !mbd.isSynthetic()) { // 調(diào)用BeanPostProcessor接口中的postProcessAfterInitialization()方法 // AOP代理就在AnnotationAwareAspectJAutoProxyCreator類(lèi)此方法中 // AnnotationAwareAspectJAutoProxyCreator的父類(lèi)AbstractAutoProxyCreator實(shí)現(xiàn)了此方法 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
上面這個(gè) AnnotationAwareAspectJAutoProxyCreator 類(lèi)中的 postProcessAfterInitialization() 方法執(zhí)行過(guò)后, XService 實(shí)例就變成了 Cglib 代理對(duì)象了。
下面來(lái)分析下源碼:
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (this.earlyProxyReferences.remove(cacheKey) != bean) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { return bean; } if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); if (specificInterceptors != DO_NOT_PROXY) { this.advisedBeans.put(cacheKey, Boolean.TRUE); // 創(chuàng)建代理對(duì)象 Object proxy = createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; }
protected Object createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) { if (this.beanFactory instanceof ConfigurableListableBeanFactory) { AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass); } ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.copyFrom(this); if (!proxyFactory.isProxyTargetClass()) { if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else { evaluateProxyInterfaces(beanClass, proxyFactory); } } Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); proxyFactory.addAdvisors(advisors); proxyFactory.setTargetSource(targetSource); customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } return proxyFactory.getProxy(getProxyClassLoader()); } public Object getProxy(@Nullable ClassLoader classLoader) { return createAopProxy().getProxy(classLoader); } protected final synchronized AopProxy createAopProxy() { if (!this.active) { activate(); } return getAopProxyFactory().createAopProxy(this); } public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { // 這個(gè)判斷很重要,可以通過(guò)配置文件進(jìn)行配置,來(lái)決定采用什么動(dòng)態(tài)代理 if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<?> targetClass = config.getTargetClass(); if (targetClass == null) { // 拋異常略 } if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { // 創(chuàng)建JDK動(dòng)態(tài)代理 return new JdkDynamicAopProxy(config); } // 創(chuàng)建Cglib動(dòng)態(tài)代理 return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } }
三、小結(jié)
AOP的原理和Mybatis的原理一樣,都是利用了Spring中@Import導(dǎo)入ImportBeanDefinitionRegistrar這個(gè)擴(kuò)展點(diǎn)。
先往容器中添加一個(gè)BeanDefinition,然后再適當(dāng)?shù)臅r(shí)機(jī)進(jìn)行方法的調(diào)用。
到此這篇關(guān)于Spring中的AOP動(dòng)態(tài)代理源碼詳解的文章就介紹到這了,更多相關(guān)AOP動(dòng)態(tài)代理源碼內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用IDEA對(duì)SpringBoot應(yīng)用進(jìn)行遠(yuǎn)程調(diào)試方式
文章介紹了如何在IDEA中對(duì)部署在服務(wù)器上的SpringBoot應(yīng)用進(jìn)行遠(yuǎn)程調(diào)試,通過(guò)配置遠(yuǎn)程調(diào)試端口和啟動(dòng)參數(shù),本地IDEA可以設(shè)置斷點(diǎn)并進(jìn)行調(diào)試2025-02-02java json 省市級(jí)聯(lián)實(shí)例代碼
這篇文章介紹了java json 省市級(jí)聯(lián)實(shí)例代碼,有需要的朋友可以參考一下2013-09-09SwiftUI中級(jí)List如何添加新內(nèi)容(2020年教程)
這篇文章主要介紹了SwiftUI中級(jí)List如何添加新內(nèi)容,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01spring+hibernate 兩種整合方式配置文件的方法
本篇文章主要介紹了spring+hibernate 兩種整合方式配置文件的方法,主要有兩種方式 1、注解方式 2、xml方式實(shí)現(xiàn),有興趣的可以了解一下。2017-04-04SpringBoot核心@SpringBootApplication使用介紹
這篇文章主要介紹了SpringBoot核心@SpringBootApplication的使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03java程序員如何編寫(xiě)更好的單元測(cè)試的7個(gè)技巧
測(cè)試是開(kāi)發(fā)的一個(gè)非常重要的方面,可以在很大程度上決定一個(gè)應(yīng)用程序的命運(yùn)。良好的測(cè)試可以在早期捕獲導(dǎo)致應(yīng)用程序崩潰的問(wèn)題,但較差的測(cè)試往往總是導(dǎo)致故障和停機(jī)。本文主要介紹java程序員編寫(xiě)更好的單元測(cè)試的7個(gè)技巧。下面跟著小編一起來(lái)看下吧2017-03-03Java實(shí)現(xiàn)自定義中文排序的方法機(jī)注意事項(xiàng)
在Java中,中文排序通常涉及到使用Collator類(lèi)來(lái)處理字符串的比較,確保根據(jù)漢字的拼音順序進(jìn)行排序,本文給大家介紹了Java實(shí)現(xiàn)自定義中文排序的方法機(jī)注意事項(xiàng),并有相關(guān)的代碼示例供大家參考,需要的朋友可以參考下2024-10-10Java利用for循環(huán)輸出空心菱形的實(shí)例代碼
這篇文章主要介紹了Java利用for循環(huán)輸出空心菱形的實(shí)例代碼,需要的朋友可以參考下2014-02-02SpringBoot 指標(biāo)監(jiān)控actuator的專(zhuān)題
未來(lái)每一個(gè)微服務(wù)在云上部署以后,我們都需要對(duì)其進(jìn)行監(jiān)控、追蹤、審計(jì)、控制等。SpringBoot就抽取了Actuator場(chǎng)景,使得我們每個(gè)微服務(wù)快速引用即可獲得生產(chǎn)級(jí)別的應(yīng)用監(jiān)控、審計(jì)等功能,通讀本篇對(duì)大家的學(xué)習(xí)或工作具有一定的價(jià)值,需要的朋友可以參考下2021-11-11