原来只是想看下Spring事务管理的原理,但在寻找事务起作用的源头时,就把Aop的代码几乎看遍了。。。所以就顺便写了一篇关于Aop原理的文章。希望能帮到大家( ^_^ )
和看事务管理一样,还是根据SpringBoot配置了哪些关键类来分析原理。可以从Spring.factories找到Spring自动配置类 AopAutoConfiguration
。该类根据配置文件有没有spring.aop.auto=true(该值默认为true)。该类上添加了 @EnableAspectJAutoProxy
注解,所以我们可以很清楚的看出,springboot默认是开启aop功能的。而 @EnableAspectJAutoProxy
向spring容器中添加了自定义配置Aop起作用的关键类 AnnotationAwareAspectJAutoProxyCreator
SpringBoot自动配置给容器加入了Aop的核心类, AnnotationAwareAspectJAutoProxyCreator
,该类实现了SmartInstantiationAwareBeanPostProcessor接口,所以在bean的创建前后分别会调用该类的 postProcessBeforeInstantiation
和 postProcessAfterInstantiation
方法。
postProcessBeforeInstantiation
方法会获取TargetSource来在对象创建前调用createProxy来创建代理对象。目前还没搞清楚什么情况会有TargetSource。 postProcessAfterInstantiation
方法调用wrapIfNecessary方法,先获取所有的切点拦截器,创建的时候与代理类所绑定。具体创建代理类的逻辑实在是没看懂,Spring自己封装了cglib代理类实现,不过也是创建了 DynamicAdvisedInterceptor
为主拦截器的代理类,还有之前查找的所有切面拦截器。下面源码就是Spirng通过我们配置的切面表示创建Advisor的过程。
public List<Advisor> buildAspectJAdvisors() { List<String> aspectNames = this.aspectBeanNames; //第一次去获取切面配置类 if (aspectNames == null) { synchronized (this) { aspectNames = this.aspectBeanNames; if (aspectNames == null) { // 获取所有类名 遍历 for (String beanName : beanNames) { Class<?> beanType = this.beanFactory.getType(beanName); // 如果该类有@Aspect注解,并且不是AspectJ类 //We need to detect this as "code-style" AspectJ aspects should not be interpreted by Spring AOP. if (this.advisorFactory.isAspect(beanType)) { aspectNames.add(beanName); AspectMetadata amd = new AspectMetadata(beanType, beanName); if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) { MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName); //创建对方法进行增强处理的Advisor(InstantiationModelAwarePointcutAdvisorImpl) //该增强器默认有AspectJExpressionPointcut作为你匹配,之后进行matches是会使用 List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory); if (this.beanFactory.isSingleton(beanName)) { this.advisorsCache.put(beanName, classAdvisors); } else { this.aspectFactoryCache.put(beanName, factory); } advisors.addAll(classAdvisors); } else { // Per target or per this. if (this.beanFactory.isSingleton(beanName)) { throw new IllegalArgumentException("Bean with name '" + beanName + "' is a singleton, but aspect instantiation model is not singleton"); } MetadataAwareAspectInstanceFactory factory = new PrototypeAspectInstanceFactory(this.beanFactory, beanName); this.aspectFactoryCache.put(beanName, factory); advisors.addAll(this.advisorFactory.getAdvisors(factory)); } } } this.aspectBeanNames = aspectNames; return advisors; } } } return advisors; } 复制代码
DynamicAdvisedInterceptor
类是Aop每个代理类都有的拦截器,当调用代理类的方法时,首先会调用该类的
intercept
方法。
@Override @Nullable 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 { // 对aop暴露进行处理,如果暴露则将代理类置入当前线程中,之后嵌套调用可以取到 if (this.advised.exposeProxy) { // Make invocation available if necessary. oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } // 获取原始对象(代理前对象) target = targetSource.getTarget(); Class<?> targetClass = (target != null ? target.getClass() : null); // 获取拦截器链,就是在创建代理类前获取的拦截处理器,对方法进行匹配,和之前讲的事务Advisor一样 // 通过MethodMatcher来匹配,这边是AspectJExpressionPointcut的mathces对表达式进行解析 // 自定义的切面是通过之前的Advisor来生成的拦截器 // MethodBeforeAdviceAdapter AfterReturningAdviceAdapter ThrowsAdviceAdapter //通过是否匹配上面三种adapter分别生成 //MethodBeforeAdviceInterceptor AfterReturningAdviceInterceptor ThrowsAdviceInterceptor List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); Object retVal; if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) { // 没有增强处理器直接执行原始对象的方法 Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = methodProxy.invoke(target, argsToUse); } else { //调用CglibMethodInvocation.process(), //该方法会递归执行所有拦截器链中的方法,知道调用完成原始方法 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); } } } 复制代码
@EnableAsync
可以开启Spring管理的线程池,利用注解方式简单实现方法多线程调用。但是有一点需要注意(我觉得是Spring的bug),该注解实现还是利用的Aop,但是使用另一个Bean后置处理器: AsyncAnnotationBeanPostProcessor
,从下面代码可以看出,在bean创建完成后会对未代理过的类创建代理对象,如果已经是代理类则添加一个切面处理器进去。由于在新创建代理类的时候使用的是独立的后置处理器,所以在切面设置的一些属性对 @Async
无效(例如expose暴露)。所以如果想让只有 @Async
注解的代理类,想要使暴露生效只能额外对该后置处理器添加属性。
@Override public Object postProcessAfterInitialization(Object bean, String beanName) { if (this.advisor == null || bean instanceof AopInfrastructureBean) { // Ignore AOP infrastructure such as scoped proxies. return bean; } // 如果该bean已经被处理过(代理类) if (bean instanceof Advised) { Advised advised = (Advised) bean; // 如果需要被处理(有@Async注解) if (!advised.isFrozen() && isEligible(AopUtils.getTargetClass(bean))) { // Add our local Advisor to the existing proxy's Advisor chain... if (this.beforeExistingAdvisors) { advised.addAdvisor(0, this.advisor); } else { advised.addAdvisor(this.advisor); } return bean; } } // 如果需要被处理(有@Async注解) if (isEligible(bean, beanName)) { ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName); if (!proxyFactory.isProxyTargetClass()) { evaluateProxyInterfaces(bean.getClass(), proxyFactory); } proxyFactory.addAdvisor(this.advisor); customizeProxyFactory(proxyFactory); return proxyFactory.getProxy(getProxyClassLoader()); } // No proxy needed. return bean; } 复制代码
Spring通过为元类创建代理类添加 DynamicAdvisedInterceptor
的拦截器来实现拦截器链,通过拦截器链我们自己创建的切面添加到拦截器链当中(可以自定义顺序),这样非常灵活方便的为我们提供了对类方法扩展的功能。 另外推荐一篇对AOP扩展的文章,写的很好。 觉得本文对你有帮助的小伙伴不妨点个赞,你们的关注是我继续下去的动力。