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底层。
当你的才华还撑不起你的野心的时候,
你就应该静下心来学习;
当你的能力还驾驭不了你的目标时,
就应该沉下心来,历练.