【spring原始碼】六、@EnableAspectJAutoProxy
⑤invokeBeanFactoryPostProcessors()
先說明:invokeBeanFactoryPostProcessors()是在refresh()方法中的第⑤步,他的作用是註冊bean的定義資訊,但還沒進行建立例項。我們下面介紹了註解@EnableAspectJAutoProxy就是在這個階段註冊一個bean定義,但例項化要推遲到第⑥步registerBeanPostProcessor()完成
@EnableAspectJAutoProxy
@EnableAspectJAutoProxy
的作用是給spring容器中註冊一個bean:這個bean名為internalAutoProxyCreator,型別為AnnotationAwareAspectJAutoProxyCreator.class “註冊裝配模式的切面自動代理建立器”另外可以注意,是在
invokeBeanFactoryPostProcessors()
階段進來呼叫註冊的
@EnableAspectJAutoProxy標準在配置類上,在EnableAspectJAutoProxy介面類上有@Import(AspectJAutoProxyRegistrar.class)
,該@Import給容器中匯入了AspectJAutoProxyRegistrar這個bean,而這個bean作用是手動註冊bean定義到ac容器中。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({AspectJAutoProxyRegistrar.class})
public @interface EnableAspectJAutoProxy {
// 用於強制使用cglib動態代理,即使實現了介面。
// 如果希望強制使用CGLIB代理(例如希望代理目標物件的所有方法,而不只是實現自介面的方法)// 但需要保證有CGLIB包
boolean proxyTargetClass() default false;
// 事務中會用到 // 是否暴露代理物件,暴露出來的代理物件和執行緒繫結,用的是threadLocal // 設定為true之後還得用(AopContext.currentProxy()).被調方法() 替換原來的 被調方法()
// 比如切入點表示式是save方法,saveAll方法沒在切入點表示式裡,saveAll呼叫了save方法,此時呼叫saveAll方法並不執行save的AOP方法//走save的時候該輪到增強的事情已經過去了//AopContext.currentProxy()獲取代理物件
boolean exposeProxy() default false;
}
exposeProxy解釋:
public interface UserService{ public void a(); public void a(); } public class UserServiceImpl implements UserService{ @Transactional(propagation = Propagation.REQUIRED) public void a(){ this.b(); } @Transactional(propagation = Propagation.REQUIRED_NEW) public void b(){ System.out.println("b has been called"); } } 程式碼參照《Spring原始碼解析》p173頁。 Q1:b中的事務會不會生效? A1:不會,a的事務會生效,b中不會有事務,因為a中呼叫b屬於內部呼叫,沒有通過代理,所以不會有事務產生。 Q2:如果想要b中有事務存在,要如何做? A2:<aop:aspectj-autoproxy expose-proxy=“true”> ,設定expose-proxy屬性為true,將代理暴露出來,使用AopContext.currentProxy()獲取當前代理,將this.b()改為((UserService)AopContext.currentProxy()).b()
Import(AspectJAutoProxyRegistrar)
而註解驅動裡的知識告訴我們@Import與實現ImportBeanDefinitionRegistrar介面的類註冊bean的用法,這時@Import就會呼叫這個類的
registerBeanDefinitions()
方法,(可以在這個方法上打斷點)
class AspectJAutoProxyRegistrar
implements ImportBeanDefinitionRegistrar { // 實現該介面的話會自動呼叫registerBeanDefinitions()方法
@Override
public void registerBeanDefinitions(//註冊bean定義,而不是註冊bean例項
AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {//bean定義註冊器
// 去註冊bean // 如有必要就註冊AspectJ註解自動代理建立器
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
// 拿到註解@EnableAspectJAutoProxy註解的屬性資訊,proxyTargetClass、exposeProxy
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 abstract class AopConfigUtils {
// 註冊類
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, //AnnotationAwareAspectJAutoProxyCreator.class
BeanDefinitionRegistry registry, //註冊器
@Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
// 如果bean定義存在了
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;
}
// else 如果該bean定義不存在
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);//AnnotationAwareAspectJAutoProxyCreator.class
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// 註冊bean定義
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
比如現在我們有個邏輯(有紅藍色顏料就能造出彩虹),該方法可以通過
registry.containsBeanDefinition("com.atguigu.bean.MyRed");
判斷容器中是否有了對應的紅bean(的定義資訊),同理還判斷有沒有藍bean定義,如紅藍bean定義資訊都有,就建立一個彩虹BeanDefinition定義資訊,:new RootBeanDefinition(RainBow.class);
,然後註冊bean定義資訊到容器中:registry.registerBeanDefinition("rainBow", beanDefinition);
從而建立bean的時候工廠容器就知道要建立哪些bean了。
也就是說:@Import(AspectJAutoProxyRegistrar)的作用的註冊一個bean定義資訊:這個bean名為internalAutoProxyCreator,型別為AnnotationAwareAspectJAutoProxyCreator.class
AnnotationAwareAspectJAutoProxyCreator
“org.springframework.aop.config.internalAutoProxyCreator”
上面說了:AspectJAutoProxyRegistrar的作用的註冊一個bean:internalAutoProxyCreator
。而internalAutoProxyCreator是bean name,對應的值是類AnnotationAwareAspectJAutoProxyCreator
(註解裝配方式的切面自動代理建立器)。他是一個後置處理器。AnnotationAwareAspectJAutoProxyCreator的繼承關係如下:
類繼承關係
public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {}
public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator {}
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {}
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {}
總結關係如下:
---AnnotationAwareAspectJAutoProxyCreator
------AnnotationAwareAspectJAutoProxyCreator
--------->AspectJAwareAdvisorAutoProxyCreator
------------>AbstractAdvisorAutoProxyCreator
--------------->AbstractAutoProxyCreator
------------------>BeanFactoryAware //(這個介面可以把bean工廠拿到)
------------------>SmartInstantiationAwareBeanPostProcessor //(注意這個)
---------------------->InstantiationAwareBeanPostProcessor
-------------------------->BeanPostProcessor
每個類的作用:
==父類-->子類
=====AbstractAutoProxyCreator======
public void setBeanFactory(BeanFactory beanFactory) {}
public boolean postProcessBeforeInstantiation();
public boolean postProcessAfterInstantiation(Object bean, String beanName) {}
=====AbstractAdvisorAutoProxyCreator========;
public void setBeanFactory(BeanFactory beanFactory);{initBeanFactory((ConfigurableListableBeanFactory)beanFactory);}//子類重寫了setBeanFactory方法//refresh(){registerBeanPostProcessor(){這裡呼叫了set方法}}
========AspectJAwareAdvisorAutoProxyCreator===========;
========AnnotationAwareAspectJAutoProxyCreator====;
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {}//前面的setBeanFactory呼叫了該方法,這裡重寫了
如果想了解xml方式的AspectJAwareAdvisorAutoProxyCreator是如何注入到容器的,可以參考https://blog.csdn.net/qq_26323323/article/details/81012855
第⑤部分更多的內容我們放後面點擴充部分再講
AnnotationAwareAspectJAutoProxyCreator註冊時機
這裡說下流程,具體步驟可以看後文的附錄的⑤
main方法
invokeBeanFactoryPostPostProcessors() 註冊bean工廠的後置處理器
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
遍歷所有所有bean工廠後置處理器,依次例項化工廠後置處理器,然後依次呼叫他們裡面重寫了的registerBeanDefinitions方法
refresh();
invokeBeanFactoryPostProcessors(beanFactory);
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
postProcessor.postProcessBeanDefinitionRegistry(registry);//
processConfigBeanDefinitions(registry);
this.reader.loadBeanDefinitions(configClasses);//ConfigurationClassPostProcessor.java
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);//此處的變數內容如下圖 //並不是每個configModel都會走這個方法
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
registrars.forEach((registrar, metadata) ->
registrar.registerBeanDefinitions(metadata, this.registry, this.importBeanNameGenerator));
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")) {//jdk動態代理還是CGLIB動態代理
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {//暴露代理物件
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);//就是給bean定義中新增一個屬性是exposeProxy
}
}
}
相關文章
- Spring原始碼之六-onRefresh()方法Spring原始碼
- Spring Security原始碼分析六:Spring Social社交登入原始碼解析Spring原始碼
- Spring原始碼-AOP(六)-AOP代理的建立Spring原始碼
- Spring原理與原始碼分析系列(六)- Spring AOP入門與概述Spring原始碼
- Spring原始碼分析——搭建spring原始碼Spring原始碼
- Spring原始碼剖析9:Spring事務原始碼剖析Spring原始碼
- Spring原始碼分析——spring原始碼之obtainFreshBeanFactory()介紹Spring原始碼AIBean
- 5.2 spring5原始碼--spring AOP原始碼分析三---切面原始碼分析Spring原始碼
- Spring原始碼系列:BeanDefinition原始碼解析Spring原始碼Bean
- Spring原始碼分析(六)SpringAOP例項及標籤的解析Spring原始碼
- 5.1 Spring5原始碼--Spring AOP原始碼分析一Spring原始碼
- Spring原始碼分析——spring原始碼核心方法refresh()介紹Spring原始碼
- 5.2 Spring5原始碼--Spring AOP原始碼分析二Spring原始碼
- Spring原始碼心得Spring原始碼
- Spring原始碼分析Spring原始碼
- 【Spring原始碼分析】AOP原始碼解析(上篇)Spring原始碼
- 【Spring原始碼分析】AOP原始碼解析(下篇)Spring原始碼
- Giraph原始碼分析(六)——Edge 分析原始碼
- java集合原始碼分析(六):HashMapJava原始碼HashMap
- spring boot碼雲原始碼Spring Boot原始碼
- Spring原始碼深度解析(郝佳)-學習-原始碼解析-Spring MVCSpring原始碼MVC
- 【spring原始碼學習】spring的事務管理的原始碼解析Spring原始碼
- Spring原始碼之IOC(一)BeanDefinition原始碼解析Spring原始碼Bean
- [譯] 學習 Spring Security(六):密碼編碼Spring密碼
- spring學習:spring原始碼_BeanDefinitionSpring原始碼Bean
- 如何看Spring原始碼Spring原始碼
- Spring AOP 原始碼解析Spring原始碼
- Spring之事務原始碼Spring原始碼
- Spring cache原始碼分析Spring原始碼
- Spring原始碼分析-BeanFactoryPostProcessorSpring原始碼Bean
- Spring原始碼編譯Spring原始碼編譯
- spring原始碼基礎Spring原始碼
- 原始碼閱讀:SDWebImage(六)——SDWebImageCoderHelper原始碼Web
- Vue 原始碼閱讀(六)元件化Vue原始碼元件化
- Spring Cloud原始碼分析之Eureka篇第六章:服務註冊SpringCloud原始碼
- 【spring原始碼學習】spring的遠端呼叫實現原始碼分析Spring原始碼
- Spring原始碼系列(二)--bean元件的原始碼分析Spring原始碼Bean元件
- Spring原始碼剖析6:Spring AOP概述Spring原始碼