Spring AOP源码解析
文章目录
前言
本文主要介绍Spring AOP原理
AOP底层原理
1、@EnableAspectJAutoProxy
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({AspectJAutoProxyRegistrar.class})
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}
@Import({AspectJAutoProxyRegistrar.class})
给容器中导入AspectJAutoProxyRegistrar类,这个类实现了ImportBeanDefinitionRegistrar
接口,可以添加自定义组件。
在AspectJAutoProxyRegistrar里核心的地方是
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
这个AOP的工具类主要作用是把AnnotationAwareAspectJAutoProxyCreator
这个类的BeanDefinition信息注册到spring容器中。
@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());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
//改变bean最重要的就是改变bean所对应的className属性
apcDefinition.setBeanClassName(cls.getName());
}
}
//如果已经存在自动代理创建器并且与将要创建的一致,那么无需再次创建
return null;
} else {
//生成BeanDefinition信息
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", -2147483648);
beanDefinition.setRole(2);
//加类定义信息注册到Spring容器
registry.registerBeanDefinition(
"org.springframework.aop.config.internalAutoProxyCreator", beanDefinition);
return beanDefinition;
}
}
2、AspectJAwareAdvisorAutoProxyCreator
从类图可以了解到AspectJAwareAdvisorAutoProxyCreator
这个类的功能。
实现了一系列Aware的接口,在Bean装载的时候获取BeanFactory(Bean工厂),Bean的ClassLoader,还实现了Order接口,继承了ProxyConfig,ProxyConfig中主要封装了代理的通用处理逻辑,比如选择JDK动态代理或者CGLIB代理。
JDK动态代理:其代理对象必须是某个接口的实现,它通过在运行期间创建一个接口的实现类来完成对目标对象的代理。
CGLIB代理:实现原理类似于JDK动态代理,只是它在运行期间生成的代理对象时针对目标类扩展的子类。CGLIB是高效的代码生成包,底层是依靠ASM操作字节码实现的,性能比JDK强。
能够让这个类参与到Bean初始化过程,是由于这个类实现了BeanPostProcessor接口(后置处理器)。
3、AOP流程
3.1、容器创建
- 传入配置类,创建IOC容器
- 注册配置类
- 调用refresh方法刷新容器
public class TestAop {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new
AnnotationConfigApplicationContext(MainConfigAop.class);
MathCalculator mathCalculator = context.getBean(MathCalculator.class);
System.out.println(mathCalculator.dev(2, 1));
context.close();
}
}
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
this.register(componentClasses);
this.refresh();
}
3.2、注册后置处理器
使用registerBeanPostProcessors(beanFactory)注册Bean的后置处理器,来拦截Bean的创建。
-
先获取IOC容器中已经定义了并且需要创建对象的
BeanPostProcessor
-
给容器中添加其他后置处理器
beanFactory.addBeanPostProcessor (new PostProcessorRegistrationDelegate.BeanPostProcessorChecker( beanFactory,beanProcessorTargetCount));
-
优先创建实现
PriorityOrdered
接口的BeanPostProcessor对象。添加到beanFactory中。 -
再创建实现
Ordered
接口的BeanPostProcessor对象。添加到beanFactory中。 -
之后创建没有实现
Ordered
接口的BeanPostProcessor对象。添加到beanFactory中。 -
给容器中添加其他后置处理器
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
创建BeanPostProcessor对象过程
以创建internalAutoProxyCreator的BeanPostProcessor为例。
-
在doCreateBean中,首先创建Bean的实例
instanceWrapper = this.createBeanInstance(beanName, mbd, args);
-
给属性赋值
this.populateBean(beanName, mbd, instanceWrapper);
-
初始化Bean
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
-
初始化Aware接口的方法回调 例如设置BeanFactory
this.invokeAwareMethods(beanName, bean); //看bean是否实现XXXAware接口,如果有实现就设置相应值 private void invokeAwareMethods(String beanName, Object bean) { if (bean instanceof Aware) { if (bean instanceof BeanNameAware) { ((BeanNameAware)bean).setBeanName(beanName); } if (bean instanceof BeanClassLoaderAware) { ClassLoader bcl = this.getBeanClassLoader(); if (bcl != null) { ((BeanClassLoaderAware)bean).setBeanClassLoader(bcl); } } if (bean instanceof BeanFactoryAware) { ((BeanFactoryAware)bean).setBeanFactory(this); } } }
-
执行后置处理器的
postProcessBeforeInitialization
方法wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
-
执行自定义初始化方法
this.invokeInitMethods(beanName, wrappedBean, mbd);
-
执行后置处理器的
postProcessAfterInitialization
方法wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
-
-
到此为止,
AnnotationAwareAspectJAutoProxyCreator
类型的BeanPostProcessor对象创建成功。 -
注册到beanFactory中
registerBeanPostProcessors(beanFactory, xxxPostProcessors) private static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) { Iterator var2 = postProcessors.iterator(); while(var2.hasNext()) { BeanPostProcessor postProcessor = (BeanPostProcessor)var2.next(); //添加到beanFactory中 beanFactory.addBeanPostProcessor(postProcessor); } }
3.3、初始化剩下的单实例Bean
完成BeanFactory的初始化工作
finishBeanFactoryInitialization(beanFactory);
-
遍历获取容器中所有得Bean,依次创建对象。经历过程 getBean->doGetBean->getSingleton
-
创建Bean(业务逻辑组件和切面组件)
-
先从缓存中获取当前Bean,如果能获取到,说明Bean是之前创建过的,直接使用,否则需创建。(只要创建好的Bean都会被缓存起来,这是Spring保证单实例Bean的实现原理)
先从缓存中检查有没有这个 Bean // Eagerly check singleton cache for manually registered singletons. Object sharedInstance = getSingleton(beanName); 如果等于null,才会继续执行下面的方法 sharedInstance = getSingleton(beanName, () -> { try { return this.createBean(beanName, mbd, args); } catch (BeansException var5) { this.destroySingleton(beanName); throw var5; } });
-
createBean 创建Bean。
AnnotationAwareAspectJAutoProxyCreator
会在Bean创建之前先尝试返回Bean的实例。BeanPostProcessor:
是对象创建Bean完成进行初始化前后调用的。InstantiationAwareBeanPostProcessor:
是创建Bean实例之前先尝试用后置处理器返回对象。- 实例化:指创建类实例(对象)的过程。比如使用构造方法new对象,为对象在内存中分配空间。(要创建对象,但是并未生成对象)
- 初始化:指为类中各个类成员(被static修饰的成员变量)赋初始值的过程,是类生命周期中的一个阶段。简单理解为对象中的属性赋值的过程。(对象已经生成,为其属性赋值)
-
解析BeforeInstantiation,希望后置处理器在此能返回一个代理对象,如果能返回就使用该对象;不能返回就继续执行创建。
beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
@Nullable protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { Object bean = null; if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) { Class<?> targetType = this.determineTargetType(beanName, mbd); if (targetType != null) { //InstantiationAwareBeanPostProcessor 类型的后处理器进行 //postProcessBeforelnstantiation 方法 bean = this.applyBeanPostProcessorsBeforeInstantiation(targetType,beanName); if (bean != null) { //如果实例已经存在 //BeanPostProcessor类型的postProcessAfterlnitialization方法的调用。 bean = this.applyBeanPostProcessorsAfterInitialization(bean,beanName); } } } mbd.beforeInstantiationResolved = bean != null; } return bean; }
-
真正的去创建一个Bean,和之前3.2.6的流程是一样的。
beanInstance = this.doCreateBean(beanName, mbdToUse, args);
AnnotationAwareAspectJAutoProxyCreator
会在任何 Bean 创建完成之前先尝试返回 Bean 的实例,因为它实现了InstantiationAwareBeanPostProcessor
接口,这个接口有两个方法,一个postProcessBeforeInstantiation
,另一个postProcessAfterInstantiation
,这两个方法是在 Bean 创建完成前后执行的,而BeanPostProcessor
接口的两个方法是在创建完成并且初始化前后调用的。-
在每一个Bean创建之前调用
applyBeanPostProcessorsBeforeInstantiation
方法中会拿到所有后置处理器,判断如果是InstantiationAwareBeanPostProcessor
类型的,就执行postProcessBeforeInstantiation
方法。if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp; Object result = ibp.postProcessBeforeInstantiation(beanClass,beanName);
在
postProcessBeforeInstantiation
方法中-
判断当前Bean是否在advisedBeans(保存了所有需要增强的bean)中
-
判断当前Bean是否是基础类型Advice、PointCut、Advisor、AopInfrastructureBean,或者是否是切面(@Aspect)
-
判断是否该跳过
-
获取候选的增强器(切面里面的通知方法)每一个封装的通知方法的增强器是
InstantiationModelAwarePointcutAdvisor
-
判断每一个增强器是否是
AspectJPointcutAdvisor
类型的,如果是就返回true,不是就返回false。
protected boolean shouldSkip(Class<?> beanClass, String beanName) { List<Advisor> candidateAdvisors = this.findCandidateAdvisors(); Iterator var4 = candidateAdvisors.iterator(); Advisor advisor; do { if (!var4.hasNext()) { return super.shouldSkip(beanClass, beanName); } advisor = (Advisor)var4.next(); } while(!(advisor instanceof AspectJPointcutAdvisor) || !((AspectJPointcutAdvisor)advisor).getAspectName().equals(beanName)); return true; }
-
InstantiationAwareBeanPostProcessor
接口的postProcessAfterInstantiation
方法在populateBean中触发。该方法仍然处于实例化过程。
populateBean(beanName, mbd, instanceWrapper);//触发 postProcessAfterInstantiation方法
-
-
在 Bean 初始化之后调用
BeanPostProcessor
的postProcessAfterInitialization
方法。增强需要增强的Bean。@Override public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { if (bean != null) { //根据给定的bean的class和name构建这个key,格式:beanClassName_beanName Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.contains(cacheKey)) { //如果它适合被代理,则需要封装指定bean return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }
-
在
wrapIfNecessary
方法中,获取当前Bean的所有增强器(通知方法),判断是否需要包装(增强)。Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
@Nullable protected Object[] getAdvicesAndAdvisorsForBean( Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) { List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName); if (advisors.isEmpty()) { return DO_NOT_PROXY; } return advisors.toArray(); }
如何找到增强器呢?
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { List<Advisor> candidateAdvisors = findCandidateAdvisors(); List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }
获取所有的增强以及寻找所有增强中适用于bean的增强并应用。
-
保存当前bean到
advisedBeans
中 -
如果当前bean需要增强,创建当前bean的代理对象
Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
-
获取所有的增强器(通知方法)
-
保存到
proxyFactory
中protected Object createProxy( Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) { if (this.beanFactory instanceof ConfigurableListableBeanFactory) { AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass); } // 1.创建proxyFactory,proxy的生产主要就是在proxyFactory做的 ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.copyFrom(this); if (!proxyFactory.isProxyTargetClass()) { if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else { evaluateProxyInterfaces(beanClass, proxyFactory); } } // 2.将当前bean适合的advice,重新封装下,封装为Advisor类,然后添加到ProxyFactory中 Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); for (Advisor advisor : advisors) { proxyFactory.addAdvisor(advisor); } proxyFactory.setTargetSource(targetSource); customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } // 3.调用getProxy获取bean对应的proxy return proxyFactory.getProxy(getProxyClassLoader()); }
-
创建代理对象,spring自动决定使用哪种动态代理
// getProxy()方法 public Object getProxy(ClassLoader classLoader) { return createAopProxy().getProxy(classLoader); } // createAopProxy()方法就是决定究竟创建何种类型的proxy protected final synchronized AopProxy createAopProxy() { if (!this.active) { activate(); } // 关键方法createAopProxy() return getAopProxyFactory().createAopProxy(this); } // createAopProxy() public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { // 1.config.isOptimize()是否使用优化的代理策略,目前使用与CGLIB // config.isProxyTargetClass() 是否目标类本身被代理而不是目标类的接口 // hasNoUserSuppliedProxyInterfaces()是否存在代理接口 if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<?> targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } // 2.如果目标类是接口或者是代理类,则直接使用JDKproxy if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } // 3.其他情况则使用CGLIBproxy return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } }
- 给容器中返回当前组件使用cglib增强了的代理对象
- 以后容器中获取到的就是这个组件的代理对象,执行目标方法的时候,代理对象就会执行通知方法的流程。
-
-
-
3.4、目标方法的执行
容器中保存了组件的代理对象(cglib增强后的对象),这个对象里面保存了详细信息(比如增强器、目标对象)
-
org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor
的intercept
方法拦截目标方法的执行。 -
根据
ProxyFactory
对象获取将要执行的目标方法拦截器链。List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
拦截器链如何获取?
主要是在
getInterceptorsAndDynamicInterceptionAdvice
方法中。-
创建一个集合保存所有的拦截器
List<Object> interceptorList = new ArrayList(advisors.length);
一个默认的
org.springframework.aop.interceptor.ExposeInvocationInterceptor.ADVISOR
和四个增强器。 -
遍历所有的增强器,将其转为
Interceptor
Advisor[] var9 = advisors; int var10 = advisors.length; for(int var11 = 0; var11 < var10; ++var11) { Advisor advisor = var9[var11]; registry.getInterceptors(advisor);
-
将增强器转为List
-
如果本来就是MethodInterceptor,则直接加到集合中
-
如果不是,则使用
AdvisorAdapter
适配器转为MethodInterceptor
。@Override public MethodInterceptor getInterceptor(Advisor advisor) { AfterReturningAdvice advice = (AfterReturningAdvice) advisor.getAdvice(); return new AfterReturningAdviceInterceptor(advice); }
-
转化完成返回
MethodInterceptor
数组
-
-
拦截器链(每一个方法又被包装为方法拦截器,利用
MethodInterceptor
机制控制执行顺序)
-
-
如果没有拦截器链,直接执行目标方法
retVal = methodProxy.invoke(target, argsToUse);
-
如果有拦截器链,把需要执行的目标对象、目标方法、拦截器链等信息传入创建一个
CglibMethodInvocation
对象,并调用proceed()方法retVal = (new CglibAopProxy.CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy)).proceed();
-
拦截器链的触发过程,触发方法就是
proceed
@Nullable public Object proceed() throws Throwable { //如果没有拦截器或者已经到最后一个拦截器,就执行目标方法 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return this.invokeJoinpoint(); } else { //到下一个拦截器执行 Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice; Class<?> targetClass = this.targetClass != null ? this.targetClass : this.method.getDeclaringClass(); return dm.methodMatcher.matches(this.method, targetClass, this.arguments) ? dm.interceptor.invoke(this) : this.proceed(); } else { return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this); } } }
-
如果没有拦截器或者是最后一个拦截器就执行目标方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return this.invokeJoinpoint(); }
-
如果有拦截器就链式的获取每一个拦截器,拦截器执行
invoke
方法,每一个拦截器等待下一个拦截器执行完成返回以后再来执行。这里的返回值是还是拦截器,传入的是这个拦截器本身,每次调用都会减少一个长度,并且改变当前的拦截器, 所以执行顺序是栈式的结构。 return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
-
首先执行
ExposeInvocationInterceptor
拦截器的invoke方法public Object invoke(MethodInvocation mi) throws Throwable { MethodInvocation oldInvocation = (MethodInvocation)invocation.get(); invocation.set(mi); Object var3; try { var3 = mi.proceed(); } finally { invocation.set(oldInvocation); } return var3; }
代码的核心业务是放在
finally
中的,肯定会执行。下面接着进入proceed方法中。 -
再执行
AspectJAfterThrowingAdvice
拦截器的invoke方法public Object invoke(MethodInvocation mi) throws Throwable { try { return mi.proceed(); } catch (Throwable var3) { if (this.shouldInvokeOnThrowing(var3)) { this.invokeAdviceMethod(this.getJoinPointMatch(), (Object)null, var3); } throw var3; } }
注意到这里有异常的捕捉,异常发生是在这里处理的,没有异常则不会执行,继续
proceed
方法。 -
再执行
AfterReturningAdviceInterceptor
拦截器的invoke方法@Override public Object invoke(MethodInvocation mi) throws Throwable { Object retVal = mi.proceed(); this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis()); return retVal; }
继续执行proceed方法
-
再执行
AspectJAfterAdvice
拦截器的invoke方法@Override public Object invoke(MethodInvocation mi) throws Throwable { try { return mi.proceed(); } finally { invokeAdviceMethod(getJoinPointMatch(), null, null); } }
就是先执行后面的前置通知,然后执行后置通知的内容,继续执行
proceed
方法。 -
再执行
MethodBeforeAdviceInterceptor
拦截器的invoke方法@Override public Object invoke(MethodInvocation mi) throws Throwable { this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis()); return mi.proceed(); }
-
这个时候再次来到 proceed 方法,此时的下标变为 4,还是执行
MethodBeforeAdviceInterceptor
-
开始回溯了,因为方法都已经入栈了,依次执行了前置通知、后置通知、返回通知。
-
-
4、总结
1、@EnableAspectJAutoProxy 开启AOP功能
2、@EnableAspectJAutoProxy会注册一个AnnotationAwareAspectJAutoProxyCreator组件
3、AnnotationAwareAspectJAutoProxyCreator是一个后置处理器
4、容器创建过程
1、registerBeanPostProcessor()注册所有后置处理器,会创建AnnotationAwareAspectJAutoProxyCreator对象
2、finishBeanFactoryInitialize()初始化剩下的单实例bean
1)、创建业务逻辑组件和切面组件
2)、AnnotationAwareAspectJAutoProxyCreator会拦截组件的创建过程
3)、组件创建完成之后,判断组件是否需要增强
是:切面的通知方法包装成增强器(Advisor);给业务逻辑组件创建一个代理对象(cglib代理)
5 、执行目标方法:
1、代理对象执行目标方法
2、CglibProxy.intercept()
1、得到目标方法的拦截器链(增强器包装成拦截器MethodInterceptor)
2、利用拦截器的链式机制,依次进入每一个拦截器进行执行
3、效果
正常执行:前置通知->目标方法->后置通知->返回通知
异常执行: 前置通知->目标方法->后置通知->异常通知
你若盛开 清风自来 peace!
下一篇: 简单版jumpserver堡垒机安装部署