Springboot原始碼分析之EnableAspectJAutoProxy
摘要:
Spring Framwork
的兩大核心技術就是IOC
和AOP
,AOP
在Spring
的產品線中有著大量的應用。如果說反射是你通向高階的基礎,那麼代理就是你站穩高階的底氣。AOP
的本質也就是大家所熟悉的CGLIB
動態代理技術,在日常工作中想必或多或少都用過但是它背後的祕密值得我們去深思。本文主要從Spring AOP
執行過程上,結合一定的原始碼整體上介紹Spring AOP
的一個執行過程。知其然,知其所以然,才能更好的駕馭這門核心技術。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({AspectJAutoProxyRegistrar.class})
public @interface EnableAspectJAutoProxy {
//表明該類採用CGLIB代理還是使用JDK的動態代理
boolean proxyTargetClass() default false;
/**
* @since 4.3.1 代理的暴露方式:解決內部呼叫不能使用代理的場景 預設為false表示不處理
* true:這個代理就可以通過AopContext.currentProxy()獲得這個代理物件的一個副本(ThreadLocal裡面),從而我們可以很方便得在Spring框架上下文中拿到當前代理物件(處理事務時很方便)
* 必須為true才能呼叫AopContext得方法,否則報錯:Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available.
*/
boolean exposeProxy() default false;
}複製程式碼
所有的EnableXXX
驅動技術都得看他的@Import
,所以上面最重要的是這一句@Import(AspectJAutoProxyRegistrar.class)
,下面看看它
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
AspectJAutoProxyRegistrar() {
}
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,BeanDefinitionRegistry registry) {
//註冊了一個基於註解的自動代理建立器 AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata,EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
//表示強制指定了要使用CGLIB
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
//強制暴露Bean的代理物件到AopContext
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}複製程式碼
AspectJAutoProxyRegistrar
是一個項容器註冊自動代理建立器
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry,@Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class,registry,source);
}複製程式碼
說明:spring
容器的註解代理建立器就是AnnotationAwareAspectJAutoProxyCreator
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls,BeanDefinitionRegistry registry,@Nullable Object source) {
Assert.notNull(registry,"BeanDefinitionRegistry must not be null");
//這裡如果我們自己定義了這樣一個自動代理建立器就是用我們自定義的
if (registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {
BeanDefinition apcDefinition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
/**
*使用者註冊的建立器,必須是InfrastructureAdvisorAutoProxyCreator
*AspectJAwareAdvisorAutoProxyCreator,AnnotationAwareAspectJAutoProxyCreator之一
*/
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
//若使用者自己沒有定義,那就用預設的AnnotationAwareAspectJAutoProxyCreator
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
//此處注意,增加了一個屬性:最高優先順序執行,後面會和@Async註解一起使用的時候起關鍵作用
beanDefinition.getPropertyValues().add("order",Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME,beanDefinition);
return beanDefinition;
}複製程式碼
我們就成功的注入了一個Bean:AnnotationAwareAspectJAutoProxyCreator
基於註解的自動代理建立器
Spring中自動建立代理器
由此可見,Spring
使用BeanPostProcessor
讓自動生成代理。基於BeanPostProcessor
的自動代理建立器的實現類,將根據一些規則在容器例項化Bean
時為匹配的Bean
生成代理例項。
AbstractAutoProxyCreator
是對自動代理建立器的一個抽象實現。最重要的是,它實現了SmartInstantiationAwareBeanPostProcessor
介面,因此會介入到Spring IoC
容器Bean
例項化的過程。
SmartInstantiationAwareBeanPostProcessor
繼承InstantiationAwareBeanPostProcessor
所以它最主要的 職責是在bean
的初始化前,先會執行所有的InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
,誰第一個返回了不為null
的Bean
,後面就都不會執行了 。然後會再執行BeanPostProcessor#postProcessAfterInitialization
protected Object getEarlyBeanReference(String beanName,RootBeanDefinition mbd,Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject,beanName);
}
}
}
return exposedObject;
}複製程式碼
說明:這個方法是spring
的三級快取中的其中一環,當你呼叫Object earlySingletonReference = getSingleton(beanName,false);
時候就會觸發,其實還有一個地方exposedObject = initializeBean(beanName,exposedObject,mbd);
也會觸發導致返回一個代理物件。
protected Object initializeBean(final String beanName,final Object bean,@Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName,bean);
return null;
},getAccessControlContext());
}
else {
invokeAwareMethods(beanName,bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean,beanName);
}
try {
invokeInitMethods(beanName,wrappedBean,mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),beanName,"Invocation of init method failed",ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean,beanName);
}
return wrappedBean;
}複製程式碼
強調: 這2個地方雖然都有後置增強的作用,但是@Async
所使用的AsyncAnnotationBeanPostProcessor
不是SmartInstantiationAwareBeanPostProcessor
的實現類,所以此處會導致@Transactional
和@Async
處理迴圈依賴時候的不一致性。對於迴圈依賴後續會有單獨章節進行分享。
AbstractAdvisorAutoProxyCreator
如何建立代理物件後續文章在進行分析。