AOP源碼探究
AOP源碼探究:
一、@EnableAspectJAutoProxy是什麼?
-
@Import(AspectJAutoProxyRegistrar.class):給容器中導入AspectJAutoProxyRegistrar,利用AspectJAutoProxyRegistrar自定義給容器中註冊bean組件:
internalAutoProxyCreator = AnnotationAwareAspectJAutoProxyCreator
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); } } }
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);對所必須的AspectJAnnotationAutoProxyCreator組件進行註冊:
我們在源碼中可以看見,這裏註冊的class爲:AnnotationAwareAspectJAutoProxyCreator
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
所以我們可以得到這個註解的作用是:給容器中註冊一個AnnotationAwareAspectJAutoProxyCreator:自動代理創建器組件;
二、AnnotationAwareAspectJAutoProxyCreator組件的結構:
-
AnnotationAwareAspectJAutoProxyCreator
- 父類:AspectJAwareAdvisorAutoProxyCreator
- 父類:AbstractAdvisorAutoProxyCreator
- 父類:AbstractAutoProxyCreator
- 父類:ProxyProcessorSupport
- 接口:SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware
- 父類:AbstractAutoProxyCreator
- 父類:AbstractAdvisorAutoProxyCreator
- 父類:AspectJAwareAdvisorAutoProxyCreator
-
我們關注的是:
1、後置處理器的工作 BeanPostProcessor:在bean初始化前後做的事情;
2、自動裝配BeanFactory;
我們來找一下在這些子類和父類中有哪些與後置處理器和自動裝配的方法:
1、AnnotationAwareAspectJAutoProxyCreator.initBeanFactory()
2、AspectJAwareAdvisorAutoProxyCreator沒有
3、AbstractAdvisorAutoProxyCreator.setBeanFactory(),該函數還調用了:initBeanFactory
4、AbstractAutoProxyCreator.setBeanFactory()
5、AbstractAutoProxyCreator.postProcessBeforeInstantiation()
6、AbstractAutoProxyCreator.postProcessAfterInitialization()
三、流程: 定義–》註冊–》創建–》賦值、初始化–》返回
-
1、創建IOC容器:ApplicationContext applicationContext=new AnnotationConfigApplicationContext(MainConfigOfAOP.class);
-
2、註冊配置類,調用:
public AnnotationConfigApplicationContext(Class<?>... componentClasses) { this(); register(componentClasses); refresh(); }
首先註冊相關配置組件,然後刷新容器進行初始化。
-
3、我們來看refresh()函數,看一下容器的刷新過程:
-
// Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory);
這裏有一個方法:registerBeanPostProcessors註冊後置處理器,方便攔截bean的創建。
-
-
4、創建的過程:
-
1)、先獲取到IOC容器已經定了的需要創建對象的所有的BeanPostProcessor
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
-
2)、給容器中加別的BeanPostProcessor:
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length; beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
我們可以看到,我們所定義的AOP、internalAutoProxyCreator、ListenProcessor、還有我們自己加入到容器中的class:calculator
然後通過遍歷namelist加入到xxxPostProcessors中,根據不同的類型添加到不同的list中:
for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); priorityOrderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessorNames.add(ppName); } else { nonOrderedPostProcessorNames.add(ppName); } }
-
3)、分別註冊BeanPostProcessors根據不同的porcessor實現的接口的不同進行註冊。
- 首先註冊的是:實現了 PriorityOrdered接口的processor
// First, register the BeanPostProcessors that implement PriorityOrdered. sortPostProcessors(priorityOrderedPostProcessors, beanFactory); registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
- 然後註冊的是:實現了Ordered接口的processor
// Next, register the BeanPostProcessors that implement Ordered. List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size()); for (String ppName : orderedPostProcessorNames) { BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); orderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } sortPostProcessors(orderedPostProcessors, beanFactory); registerBeanPostProcessors(beanFactory, orderedPostProcessors);
- 最後註冊沒有實現接口的其他processor
// Now, register all regular BeanPostProcessors. List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size()); for (String ppName : nonOrderedPostProcessorNames) { BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); nonOrderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
**注意:**可以發現每個註冊前,都會對之排序,這個排序就控制了我們後面的鏈式執行的方法順序。
-
4)、註冊BeanPostProcessor,實際上就是創建BeanPostProcessor對象,保存在容器中。
-
創建internalAutoProxyCreator的BeanPostProcessor是哪一種情況呢?
我們可以發現:
public class ProxyProcessorSupport extends ProxyConfig implements Ordered
在ProxyProcessorSupport這個父類中實現了Ordered的接口,所以該對象走的是第二種情況的register註冊方式。
-
創建的過程:
1)、創建:bean實例
2)、 賦初值:populateBean(beanName, mbd, instanceWrapper);
3)、 初始化:exposedObject = initializeBean(beanName, exposedObject, mbd);
初始化過程:
1)、invokeAwareMethods():處理Aware接口方法的回調
2)、applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName):
初始化PostProcessorsBeforeInitialization後置處理器;
3)、invokeInitMethods(beanName, wrappedBean, mbd):
執行自定義的初始化方法;
4)、applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName):
初始化postProcessAfterInitialization後置處理器;
5)、調用setBeanFactory方法。
4)、BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator對象)
創建成功:—>aspectJAdvisorsBuilder
-
-
5)、把BeanPostProcessor註冊到BeanFactory中:beanFactory.addBeanPostProcessor(postProcessor);
以上是創建+註冊 AnnotationAwareAspectJAutoProxyCreator 的過程
AnnotationAwareAspectJAutoProxyCreator => 後置處理器是:InstantiationAwareBeanPostProcessor
-
-
5、創建的過程 詳解:
-
1)、遍歷獲取容器中所有的Bean,然後依次創建對象:getBean(beanName)
getBean() -->doGetBean()–>getSingleton()【獲取單實例bean,首先會判斷容器中是否有這個bean,如果沒有才創建,如果有就直接返回,不用重複創建】。
-
2)、創建bean:
【雖然獲取到的beanName是interalAutoProxyCretor,但是在前面已經被賦值爲
AnnotationAwareAspectJAutoProxyCreator對象,然後因爲
AnnotationAwareAspectJAutoProxyCreator是InstantiationAwareBeanPostProcessor後置處理器,
所以它會嘗試去返回,使用方法applyBeanPostProcessorsBeforeInstantiation】
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
1)、先從緩存中獲取當前bean,如果能獲取到,說明bean是之前被創建過的,直接使用;否則再創建,只要是創建好了的對象都會被緩存起來,所有的單實例只會有一個實例對象;但是注意:在如果發生了bean異常,會destroySingleton(beanName);銷燬這個實例,下一次使用的時候需要再次創建。
object = getCachedObjectForFactoryBean(beanName);
2)、createBean():創建bean:AnnotationAwareAspectJAutoProxyCreator會在任何bean創建之前先嚐試返回的實例;
注意:
1、【BeanPostProcessor是在Bean對象創建完成初始化前後調用的】
2、【InstantiationAwareBeanPostProcessor是在任何創建Bean實例之前先嚐試用後置處理器返回對象】
我們在前面已經講到AnnotationAwareAspectJAutoProxyCreator是InstantiationAwareBeanPostProcessor後置處理器的接口實現的,所以在創建的bean實例的時候,先嚐試使用後置處理器返回對象,如果從後置處理器無法返回對象,就進行創建這個對象。
3、Object beanInstance = doCreateBean(beanName, mbdToUse, args); 這纔是真正的去創建一個bean實例,和之前的創建AnnotationAwareAspectJAutoProxyCreator過程是相同的。
-
-
- 1)、
AnnotationAwareAspectJAutoProxyCreator【InstantiationAwareBeanPostProcessor】的作用: * 1)、每一個bean創建之前,調用:postProcessBeforeInstantiation(): * 關心MathCalculator和LogAspect的創建: * 1)、判斷當前bean是否在adviseBeans(保存了所有需要增強<切面>的bean)中 * 2)、判斷當前bean是否是基礎類型【Advice、Pointcut、Advisor、AopInfrastructureBean】 * 或者是否是切面(@Aspect) * 3)、是否需要跳過: * 1)、獲取候選的增強器(切面裏面的通知方法)【List<Advisor> candidateAdvisors】 * 每一個封裝的通知方法的增強器是InstantiationModelAwarePointcutAdvisor類型。 * 判斷每一個增強器是否是AspectJPointcutAdvisor類型的:返回true * 2)、永遠返回false
- 2)、
2)、創建對象【添加增強器,包裝【通知方法】】 * postProcessAfterInitialization: * return wrapIfNecessary(bean, beanName, cacheKey);包裝操作,如果需要的話。 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; } * // Create proxy if we have advice. * 1)獲取當前bean的所有增強器(通知方法) * 1、找到候選的所有的增強器(找哪些通知方法是需要切入當前bean方法的) * 2、獲取到能在bean使用的增強器 * 3、給增強器進行排序:eligibleAdvisors = sortAdvisors(eligibleAdvisors); * 2)、獲取到所有的增強器:Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); * 保存當前bean在advisedBeans中; * 3)、如果當前bean需要增強,然後創建當前bean的代理對象 * 1)、獲取所有的增強器(通知方法) * 2)、保存到proxyFactory中 * 3)、創建代理對象:Spring自動覺得 * JdkDynamicAopProxy(config);jdk動態代理 * ObjenesisCglibAopProxy(config);cglib動態代理 * 4)、給容器中返回當前組件使用cglib增強了的代理對象 * 5)、以後容器中獲取到的就是這個組件的代理對象,執行目標方法的時候,代理對象就會執行通知方法的流程
-
7.全部的bean初始化創建完畢後,使用BeanPostProcessor進行包裝,然後全部加入到對應的List中:
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
裏面,然後再對List中的所有BeanPostProcessor進行排序和註冊所有的BeanPostProcessor:
sortPostProcessors(priorityOrderedPostProcessors, beanFactory); registerBeanPostProcessors(beanFactory, orderedPostProcessors);
四、目標方法的執行:
- 容器中保存了組件的代理對象(cglib增強後的對象),這個對象裏面保存了詳細信息(比如增強器,目標對象)
1)、單步調試進入執行目標方法,就來到了CglibAopProxy這個class,它的原理其實就是通過攔截器機制,來按照指定順序來執行增加後的對象中的方法:
我們來看這個函數的源代碼:
1)、使用intercept對目標方法的攔截
2)、根據ProxyFactory對象獲取目標方法攔截器鏈:
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
1、首先進入這個函數,我們可以看到,首先判斷在cache中是否存在這個鏈,如果存在就直接返回,如果不存在,則創建:
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
MethodCacheKey cacheKey = new MethodCacheKey(method);
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
this.methodCache.put(cacheKey, cached);
}
return cached;
}
2、進入創建函數:
1)、Advisor[] advisors = config.getAdvisors(); 獲取到目標函數所擁有的所有攔截器:此處爲5:一個默認的ExposeInvocationInterceptor和4個增強器
2)、List interceptorList = new ArrayList<>(advisors.length);
新建一個攔截器鏈,來保存所有的方法攔截器:
3)、遍歷所有的增強器,將其轉化爲MethodInterceptor :
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
4)、將增強器轉爲List interceptors:
如果是MethodInterceptor,直接加入到集合中;
如果不是:那麼就使用AdvisorAdapter適配器將增強器轉爲->MethodInterceptor,轉換完成就把數組返回。
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
3、返回攔截器鏈後會存入到Cache中,以便下次訪問;
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
// We can skip creating a MethodInvocation: just invoke the target directly.
// Note that the final invoker must be an InvokerInterceptor, so we know
// it does nothing but a reflective operation on the target, and no hot
// swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else {
// We need to create a method invocation...
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
4、如果沒有攔截器鏈:直接執行目標方法:
攔截器鏈:每一個通知方法又被包裝爲方法攔截器,利用MethodInterceptor機制來達到先後執行順序。
5、如果有攔截器鏈:
就把需要執行的目標對象,目標方法,攔截器鏈等信息傳入創建一個CglibMethodInvocation對象,並調用CglibMethodInvocation.proceed()方法:
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
TargetSource targetSource = this.advised.getTargetSource();
try {
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// Check whether we only have one InvokerInterceptor: that is,
// no real advice, but just reflective invocation of the target.
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
// We can skip creating a MethodInvocation: just invoke the target directly.
// Note that the final invoker must be an InvokerInterceptor, so we know
// it does nothing but a reflective operation on the target, and no hot
// swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else {
// We need to create a method invocation...
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
// This is somewhat tricky... We have to process introductions first,
// but we need to preserve order in the ultimate list.
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
Advisor[] advisors = config.getAdvisors();
List<Object> interceptorList = new ArrayList<>(advisors.length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
Boolean hasIntroductions = null;
for (Advisor advisor : advisors) {
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match;
if (mm instanceof IntroductionAwareMethodMatcher) {
if (hasIntroductions == null) {
hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
}
match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
}
else {
match = mm.matches(method, actualClass);
}
if (match) {
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
6、攔截器的觸發過程:
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
1)、如果沒有攔截器執行目標方法,或者攔截器的索引等於攔截器數組大小-1(也就是最後一個攔截器),就直接返回;
2)、如果拿到了攔截器:
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
每次使用攔截器索引拿到攔截器後,索引加一;
每次執行proceed,索引都會自增一次:
過程: 鏈式獲取每一個攔截器,分別攔截器執行invoke方法,每一個攔截器等待下一個攔截器執行完成 返回以後再來執行;使用攔截器機制,保證通知方法與目標方法的執行順序;
五、總結:
1)、@EnableAspectJAutoProxy開啓AOP功能:@EnableAspectJAutoProxy會給容器中註冊一個組件:AnnotationAwareAspectJAutoProxyCreator
2)、AnnotationAwareAspectJAutoProxyCreator是一個後置處理器;
3)、容器的創建流程:
後置處理器的創建工作:
1)、registerBeanPostProcessors(beanFactory);註冊後置處理器;創建AnnotationAwareAspectJAutoProxyCreator對象
2)、finishBeanFactoryInitialization(beanFactory); 初始化剩下的單實例bean
1、創建業務邏輯組件和切面組件;
2、AnnotationAwareAspectJAutoProxyCreator 攔截組件的創建過程
3、在創建完對象後,會判斷組件是否需要增強:如果是:把切面的通知方法包裝成增強器(Advisor),給業務邏輯組件創建一個代理對象(相當於增強後的包裝組件)(cglib)
4)、執行目標方法:
代理對象執行目標的過程:
1)、CglibAopProxy.intercept();攔截目標方法的執行:
2)、利用攔截器的鏈式機制,依次進入每一個攔截器進行遞歸執行(先遞歸到最後一個攔截器,然後再回調執行方法)
3)、最後效果是:【順序是通過攔截器鏈的方式來控制順序】
如果方法是正常執行:前置通知—>目標方法—>後置通知—>返回通知
如果方法出現異常:前置通知—>目標方法—>後置通知—>異常通知
這一段的AOP源碼就介紹到這裏了,因爲自己的探究程度有限,希望大牛們多提出意見,大家一起更好的學習spring底層。
當你的才華還撐不起你的野心的時候,
你就應該靜下心來學習;
當你的能力還駕馭不了你的目標時,
就應該沉下心來,歷練.