我们学习了Spring AOP相关的基础知识,了解了AOP的核心概念、Spring AOP的构成及其应用场景。本篇将结合Spring的源码深入分析Spring AOP的具体实现。源码基于Spring5.3.37版本进行分析。
1.启用AOP
要想使用Spring的AOP功能,首先需要先启用它。在前一篇文章中我们知道可以通过在配置类上使用注解@EnableAspectJAutoProxy来开启对AOP的支持,因此要了解Spring AOP的启用过程,需要从此注解入手。
1.1@EnableAspectJAutoProxy
该注解源码如下:
java
代码解读
复制代码
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(AspectJAutoProxyRegistrar.class) public @interface EnableAspectJAutoProxy { boolean proxyTargetClass() default false; boolean exposeProxy() default false; }
从源码上,我们可以看到一个关键注解 @Import(AspectJAutoProxyRegistrar.class),在Spring的BeanDefinition扫描创建注册流程中,我们知道@Import注解会在配置类的扫描流程中被解析,此处@Import注解配置的AspectJAutoProxyRegistrar类由于实现了ImportBeanDefinitionRegistrar接口,因此会被实例化,并在后续步骤中调用其实现接口的默认实现方法ImportBeanDefinitionRegistrar#registerBeanDefinitions(),其内部会调用AspectJAutoProxyRegistrar实现的registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry)方法用于执行自定义的BeanDefinition扫描、创建、注册逻辑。
1.2 AspectJAutoProxyRegistrar
此类的核心作用是往Spring容器中添加了AnnotationAwareAspectJAutoProxyCreator类的BeanDefinition,由于该类实现了BeanPostProcessor的postProcessAfterInitialization() 方法,在容器启动过程中会被提前实例化,因此会在每个Bean创建的初始化后步骤中被调用。
在Spring执行BeanDefinition的扫描、创建、注册流程中,会调用此类实现的registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry)方法。此方法的核心是向Spring容器中添加了AnnotationAwareAspectJAutoProxyCreator的BeanDefinition,由于此类实现了BeanPostProcessor的postProcessAfterInitialization()方法,因此会在每个Bean创建的初始化后步骤中被调用,其UML类图如下:
2.核心流程
在Spring AOP中,最核心的流程有两部分:①代理对象创建;②代理逻辑执行。
2.1 代理对象创建
代理对象的创建入口有多个,但其核心的创建流程是一致的,下图是以代理对象创建主流程-Bean初始化后执行代理对象创建过程梳理的:
从上图可以看出,其核心步骤为:①获取符合条件的Advisor集合;②代理对象生成。接下来重点分析这两步。
2.1.1 获取符合条件的Advisor集合
寻找符合条件的Advisor的核心流程图如下所示:
每个步骤对应具体逻辑如下:
1.获取Spring容器中所有实现了Advisor接口的Bean;
2.获取Spring容器中所有Bean的类或父类上有@Aspect注解标记的Bean,通过解析类中@Pointcut、@Around、@Before、@After、@AfterReturning、@AfterThrowing注解标记的方法得到得到Advisor集合;
3.将前两步得到的Advisor集合合并;
4.判断得到的Advisor是否符合条件,判断条件如下:
- 若实现了IntroductionAdvisor接口,则调用其getClassFilter()方法获取类过滤器,判断与要代理的类是否一致,一致则符合条件。
- 若实现了PointcutAdvisor接口,则先:
- 调用其getClassFilter()方法获取类过滤器,判断与要代理的类是否一致,一致则符合条件;
- 不一致的话则调用getMethodMatcher()方法获取方法匹配器,判断当前要代理的类是否满足切点表达式,满足则符合条件。
- 若以上两种情况均未满足,则默认为满足条件,即作为公共切面逻辑。
5.对符合条件的Advisor集合进行排序。排序规则:
- 若Advisor对应类实现了PriorityOrdered,则调用实现方法获取序号;
- 否则找当前类是否实现了Ordered接口,若实现了则调用实现方法获取序号;
- 若前两步均获取为null,则将序号赋予最大值,这种情况下则会使得没有指定序号的切面逻辑按照扫描顺序进行执行。
2.1.2 代理对象生成
如果存在Advisor集合,则需要进行代理对象创建,其核心是对代理的方法做方法调用拦截,因此创建代理对象时均需传入内部实现的拦截器,以控制代理逻辑的执行。具体步骤如下:
1.组装proxyFactory,用于代理对象生成;
2.创建AopProxy,用于创建对应代理对象,分为以下两种:
- JdkDynamicAopProxy,创建条件:
- 被代理类实现了接口
- 被代理类是Proxy类类型
- 被代理类是Lambda类类型
- ObjenesisCglibAopProxy,创建条件:
- 被代理类未实现接口,且被代理类不是Proxy类类型,且被代理类不是Lambda类类型
3.创建代理对象,通过步骤2的AopProxy对象调用内部方法生成对应的代理对象,代理对象有以下两种类别:
- Jdk动态代理生成的对象
- 生成入参:JdkDynamicAopProxy,其实现了拦截器InvocationHandler接口
- CGLIB代理生成的对象
- 生成入参:针对不同的方法有不同的拦截器,拦截器均实现了MethodInterceptor接口,针对非静态业务方法主要是DynamicAdvisedInterceptor实现类
2.1.2.1 Jdk动态代理生成的对象
Jdk动态代理生成代理对象时,会将Advisor集合放到实现了InvocationHandler接口的JdkDynamicAopProxy对象里,并将JdkDynamicAopProxy对象作为入参生成了代理对象,生成的代理对象会代理目标对象的所有方法,并且所有方法内均调用了InvocationHandler接口对象的invoke()方法,用于确保代理逻辑正常执行,相关源码分析在第三节进行分析。
2.1.2.2 CGLIB代理生成的对象
CGLIB代理生成代理对象时,生成的代理对象会代理目标对象的所有方法,用于确保代理逻辑正常执行。但不同的方法会生成不同拦截器进行方法调用拦截,其中针对非静态业务方法主要是DynamicAdvisedInterceptor实现类。核心是将Advisor集合放到实现了org.springframework.cglib.proxy.MethodInterceptor接口的DynamicAdvisedInterceptor对象里,并将DynamicAdvisedInterceptor对象作为入参之一生成了代理对象,相关源码分析在第三节进行分析。
2.2 代理逻辑执行
由于代理对象会根据被代理类的情况,生成不同类别的代理对象,但其核心流程一致,其执行流程图如下所示:
整体执行流程较长,总结下来核心步骤为以下三步:
1.代理方法内部调用拦截器方法,触发代理逻辑执行;
2.构建拦截器链,Advisor对象均转换成了org.aopalliance.intercept.MethodInterceptor对象得到拦截器链;
3.递归调用拦截器链中的拦截器,以触发具体的代理逻辑执行。
这里巧妙利用递归后入先出的特性,保证了被代理方法执行前代理逻辑执行、被代理方法执行、被代理方法执行后代理逻辑执行的顺序。
2.2.1 Jdk动态代理生成的对象
Jdk动态代理生成的对象会代理目标对象的所有方法,其内部的核心逻辑是调用实现了InvocationHandler接口的对象的invoke()方法,进而进入到扩展的代理逻辑中,在代理逻辑中控制如何执行代理逻辑和被代理类的对应方法。
2.2.2 CGLIB代理生成的对象
CGLIB代理生成的对象会代理目标对象的所有方法,其内部的核心逻辑是调用实现了org.springframework.cglib.proxy.MethodInterceptor接口的对象的intercept()方法,进而进入到扩展的代理逻辑中,在代理逻辑中控制什么需要执行被代理类的对应方法。不同方法对应的拦截器并不相同,但公共非静态业务方法的拦截器为DynamicAdvisedInterceptor。
3.源码分析
3.1代理对象创建
由于代理对象的创建涉及很多类,且方法调用复杂,因此采用时序图方式,将涉及到的核心类及步骤进行展示,如下图所示:
结合前文中分析的核心步骤获取1)符合条件的Advisor集合、2)代理对象生成,选取其中核心类的方法进行源码分析。
3.1.1 查找Advisor的核心类
查找Advisor的来源分为两类,一类为实现了Spring内部Advisor接口的Bean,对应核心类为:BeanFactoryAdvisorRetrievalHelper;另一类查找 @AspectJ注解标记的切面Bean,解析@Pointcut、@Around、@Before、@After、@AfterReturning、@AfterThrowing注解标记的方法得到得到Advisor,对应核心类为BeanFactoryAspectJAdvisorsBuilder。
3.1.1.1 BeanFactoryAdvisorRetrievalHelper
此类用于查找到实现了Advisor接口的Bean,核心源码如下:
这边整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题
需要全套面试笔记的【点击此处即可】免费获取
java
代码解读
复制代码
public List<Advisor> findAdvisorBeans() { String[] advisorNames = this.cachedAdvisorBeanNames; if (advisorNames == null) { // 根据类类型获取符合条件的Bean名称,此处为了避免Bean的提前创建,所以采用获取Bean名称的方式 advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Advisor.class, true, false); this.cachedAdvisorBeanNames = advisorNames; } if (advisorNames.length == 0) { return new ArrayList<>(); } List<Advisor> advisors = new ArrayList<>(); for (String name : advisorNames) { // 省略部分代码... // 从Spring容器中获取类型是Advisor的Bean,此处只要是实现了Advisor接口的Bean均被找到 advisors.add(this.beanFactory.getBean(name, Advisor.class)); // 省略部分代码... } return advisors; }
3.1.1.2 BeanFactoryAspectJAdvisorsBuilder
此类用于查找Spring容器中所有Bean的类或父类上有@Aspect注解标记的Bean
,通过解析类中@Pointcut、@Around、@Before、@After、@AfterReturning、@AfterThrowing注解标记的方法得到得到Advisor集合,核心源码如下:
java
代码解读
复制代码
public List<Advisor> buildAspectJAdvisors() { List<String> aspectNames = this.aspectBeanNames; if (aspectNames == null) { synchronized (this) { // 省略部分代码... // 获取所有的Bean名称 String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Object.class, true, false); for (String beanName : beanNames) { // 省略部分代码... // 获取Bean对应的类类型 Class<?> beanType = this.beanFactory.getType(beanName, false); // 省略部分代码... // 如果当前类或者其父类上有@Aspect注解,则进一步解析 if (this.advisorFactory.isAspect(beanType)) { try { AspectMetadata amd = new AspectMetadata(beanType, beanName); if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) { // 创建用于创建代理对象的工厂 MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName); // 解析创建Advisor List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory); // 省略部分代码... advisors.addAll(classAdvisors); } // 省略部分代码... } this.aspectBeanNames = aspectNames; return advisors; // 省略部分代码... }
其中涉及到具体解析@AspectJ标记的类的核心类为ReflectiveAspectJAdvisorFactory,其核心源码如下:
java
代码解读
复制代码
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) { Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass(); String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName(); validate(aspectClass); MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory); List<Advisor> advisors = new ArrayList<>(); // 此处找的是@Pointcut标记的方法 for (Method method : getAdvisorMethods(aspectClass)) { if (method.equals(ClassUtils.getMostSpecificMethod(method, aspectClass))) { // 解析注解@Pointcut、@Around、@Before、@After、@AfterReturning、@AfterThrowing // 得到Advisor Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName); if (advisor != null) { advisors.add(advisor); } } } // 省略部分代码... return advisors; } public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrderInAspect, String aspectName) { validate(aspectInstanceFactory.getAspectMetadata().getAspectClass()); // 解析@Pointcut、@Around、@Before、@After、@AfterReturning、@AfterThrowing得到切点表达式对象 AspectJExpressionPointcut expressionPointcut = getPointcut( candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass()); if (expressionPointcut == null) { return null; } // 省略部分代码... // 构建Advisor对象 return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName); // 省略部分代码... }
从以上代码可以看出,解析@Pointcut、@Around、@Before、@After、@AfterReturning、@AfterThrowing注解构建Advisor的核心类为InstantiationModelAwarePointcutAdvisorImpl,其核心源码如下:
java
代码解读
复制代码
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut, Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) { // 省略部分代码... // 此处完了Advice的构建 this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut); // 省略部分代码... } // 构建Advice private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) { Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut, this.aspectInstanceFactory, this.declarationOrder, this.aspectName); return (advice != null ? advice : EMPTY_ADVICE); }
具体执行Advice对象构建的类为ReflectiveAspectJAdvisorFactory,用于解析@Around、@Before、@After、@AfterReturning、@AfterThrowing注解构建Advice对象,其核心源码如下:
java
代码解读
复制代码
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) { Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass(); validate(candidateAspectClass); // 获取当前方法的注解,获取范围为:@Pointcut、@Around、@Before、@After、@AfterReturning、@AfterThrowing AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod); // 省略部分代码... AbstractAspectJAdvice springAdvice; switch (aspectJAnnotation.getAnnotationType()) { case AtPointcut: // @Pointcut注解不做处理 if (logger.isDebugEnabled()) { logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'"); } return null; case AtAround: // 解析@Around注解 springAdvice = new AspectJAroundAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); break; case AtBefore: // 解析@Before注解 springAdvice = new AspectJMethodBeforeAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); break; case AtAfter: // 解析@After注解 springAdvice = new AspectJAfterAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); break; case AtAfterReturning: // 解析@AfterReturning注解 springAdvice = new AspectJAfterReturningAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation(); if (StringUtils.hasText(afterReturningAnnotation.returning())) { springAdvice.setReturningName(afterReturningAnnotation.returning()); } break; case AtAfterThrowing: // 解析@AfterThrowing注解 springAdvice = new AspectJAfterThrowingAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation(); if (StringUtils.hasText(afterThrowingAnnotation.throwing())) { springAdvice.setThrowingName(afterThrowingAnnotation.throwing()); } break; default: throw new UnsupportedOperationException( "Unsupported advice type on method: " + candidateAdviceMethod); } // 省略部分代码... return springAdvice; }
3.1.2 代理对象生成核心类
Spring中代理对象创建的入口为Bean初始化后调用的AbstractAutoProxyCreator的方法,其通过使用ProxyFactory根据类是否实现了接口等条件创建不同的AopProxy对象(JdkDynamicAopProxy、ObjenesisCglibAopProxy),用于创建具体的代理对象。
3.1.2.1 AbstractAutoProxyCreator
此类是一个BeanPostProcessor,实现了Bean初始化后的方法,用于代理对象的创建,其核心源码如下:
java
代码解读
复制代码
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; } protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { return bean; } if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } // 如果当前Bean是基础结构Bean,如Advisor、Advice类型的Bean等,不需要创建代理对象 if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // 获取Advisor集合 // 来源有两类:①实现了Advisor接口的Bean;②@AspectJ标记的Bean解析得到的Advisor Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); if (specificInterceptors != DO_NOT_PROXY) { this.advisedBeans.put(cacheKey, Boolean.TRUE); // 创建代理对象 Object proxy = createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } protected Object createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) { // 省略部分代码... // 创建代理对象工厂 ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.copyFrom(this); // 如果设置了通过目标类进行代理对象的创建 // 而当前Bean的类类型是Proxy或者是个Lambda类型,则找到其实现的接口 if (proxyFactory.isProxyTargetClass()) { // Explicit handling of JDK proxy targets and lambdas (for introduction advice scenarios) if (Proxy.isProxyClass(beanClass) || ClassUtils.isLambdaClass(beanClass)) { // Must allow for introductions; can't just set interfaces to the proxy's interfaces only. for (Class<?> ifc : beanClass.getInterfaces()) { proxyFactory.addInterface(ifc); } } } else { // 通过目标类进行代理对象的创建 if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else { // 通过接口进行代理对象的创建,则需要找到目标类实现的接口 evaluateProxyInterfaces(beanClass, proxyFactory); } } // 构建Advisor数组 // 包含前面查找实现了Advisor接口的Bean和解析@AspectJ标记的切面Bean, // 和通过设置指定的拦截器(实现了Advisor接口或Advice接口) Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); proxyFactory.addAdvisors(advisors); proxyFactory.setTargetSource(targetSource); customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } // Use original ClassLoader if bean class not locally loaded in overriding class loader ClassLoader classLoader = getProxyClassLoader(); if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) { classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader(); } // 创建代理对象 return proxyFactory.getProxy(classLoader); }
3.1.2.2 ProxyFactory
ProxyFactory是代理对象创建工厂,核心功能为选取合适的代理对象创建类AopProxy以及代理对象创建两部分。 选取合适的代理对象创建类对应的核心逻辑在DefaultAopProxyFactory类中,其核心源码如下:
java
代码解读
复制代码
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { // 如果配置了代理对象创建自动优化, // 或配置了通过目标类创建代理对象 // 或目标类未实现任何接口(如果只实现了SpringProxy接口也算未实现任何接口) if (!NativeDetector.inNativeImage() && (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."); } // 如果目标类是接口或是Proxy类型或是Lambda类型,则使用Jdk动态代理 if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) { return new JdkDynamicAopProxy(config); } // 否则使用CGLIB代理 return new ObjenesisCglibAopProxy(config); } else { // 以上情况不满足,则使用JDK动态代理 return new JdkDynamicAopProxy(config); } }
代理对象创建分为两种,一种是Jdk动态代理,对应核心类为JdkDynamicAopProxy;一种是CGLIB代理,对应核心类为ObjenesisCglibAopProxy。
3.1.2.3 JdkDynamicAopProxy
作为Spring对Jdk动态代理实现核心包装实现,其内部使用Jdk中的Proxy进行代理对象的创建,且还实现了InvocationHandler接口,对应实现的invoke()方法作为代理对象执行代理逻辑的总入口。
关于代理对象创建部分,其核心源码如下:
java
代码解读
复制代码
public Object getProxy(@Nullable ClassLoader classLoader) { // 省略日志输出代码... // 使用JDK自带的Proxy进行代理对象的创建 // 由于JdkDynamicAopProxy实现了InvocationHandler接口, // 因此可作为InvocationHandler类型入参,用于代理对象方法调用的拦截器,所以此处传了this return Proxy.newProxyInstance(determineClassLoader(classLoader), this.proxiedInterfaces, this); }
对于代理对象执行代理逻辑的总入口invoke(),在代理逻辑执行部分进行说明。
3.1.2.4 ObjenesisCglibAopProxy
作为Spring对CGLIB代理的包装实现,其继承了CglibAopProxy类,因此对于代理对象的创建,将对这两个类进行分析。代理对象创建的总入口在CglibAopProxy类中,其核心源码如下:
java
代码解读
复制代码
public Object getProxy(@Nullable ClassLoader classLoader) { // 省略部分代码... try { Class<?> rootClass = this.advised.getTargetClass(); Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy"); Class<?> proxySuperClass = rootClass; if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) { proxySuperClass = rootClass.getSuperclass(); Class<?>[] additionalInterfaces = rootClass.getInterfaces(); for (Class<?> additionalInterface : additionalInterfaces) { this.advised.addInterface(additionalInterface); } } // Validate the class, writing log messages as necessary. validateClassIfNecessary(proxySuperClass, classLoader); // 创建CGLIB的Enhancer对象 Enhancer enhancer = createEnhancer(); // 设置类加载器 if (classLoader != null) { enhancer.setClassLoader(classLoader); if (classLoader instanceof SmartClassLoader && ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) { enhancer.setUseCache(false); } } // 设置父类 enhancer.setSuperclass(proxySuperClass); // 设置接口 enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised)); // 设置命名规则 enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); // 设置代理类字节码创建策略 enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader)); // 将Advisor集合转换成Callback集合,用于被代理方法执行前的拦截 Callback[] callbacks = getCallbacks(rootClass); Class<?>[] types = new Class<?>[callbacks.length]; for (int x = 0; x < types.length; x++) { types[x] = callbacks[x].getClass(); } // 设置Callback过滤器,用于判断执行不同代理方法,具体使用的Callback enhancer.setCallbackFilter(new ProxyCallbackFilter( this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset)); // 设置Callback集合对于的类型 enhancer.setCallbackTypes(types); // 生成代理对象 return createProxyClassAndInstance(enhancer, callbacks); } // 省略部分代码... }
Callback
作为CGLIB代理生成的代理对象执行代理逻辑的核心逻辑,因此Advisor转换成Callback的过程也很重要,其核心源码如下:
java
代码解读
复制代码
private Callback[] getCallbacks(Class<?> rootClass) throws Exception { // Parameters used for optimization choices... boolean isFrozen = this.advised.isFrozen(); boolean exposeProxy = this.advised.isExposeProxy(); boolean isStatic = this.advised.getTargetSource().isStatic(); // CGLIB中,AOP核心拦截器 Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised); // 省略部分代码... // 此处主要是针对equals()、hashcode()方法等创建不同拦截器 Callback[] mainCallbacks = new Callback[] { aopInterceptor, // for normal advice targetInterceptor, // invoke target without considering advice, if optimized new SerializableNoOp(), // no override for methods mapped to this targetDispatcher, this.advisedDispatcher, new EqualsInterceptor(this.advised), new HashCodeInterceptor(this.advised) }; // 省略部分代码... return callbacks; }
从源码中可以看到,CGLIB代理生成的代理对象,其核心代理逻辑主要在DynamicAdvisedInterceptor
中。 代理对象的创建逻辑中具体代理对象的创建在createProxyClassAndInstance()方法中,其对应源码在ObjenesisCglibAopProxy类中,其核心源码如下:
java
代码解读
复制代码
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) { // 设置实例化过程中不进行拦截 enhancer.setInterceptDuringConstruction(false); // 设置拦截器 enhancer.setCallbacks(callbacks); // 创建代理对象 return (this.constructorArgs != null && this.constructorArgTypes != null ? enhancer.create(this.constructorArgTypes, this.constructorArgs) : enhancer.create()); }
3.2代理逻辑执行
从代理对象的创建可以看到,Jdk动态代理和CGLIB代理创建的代理对象存在差异,因此其执行逻辑也存在差异,接下来将针对两种代理对象分别进行分析。
在分析之前,我们先基于以下接口及其实现类作为代理对象生成的父类/接口。
java
代码解读
复制代码
public interface OriginServiceInterface { void test(); } @Component("originService") public class OriginService implements OriginServiceInterface { @Override public void test() { System.out.println("origin..."); } }
3.2.1 Jdk动态代理对象
Jdk动态代理生成的代理对象如下所示,由于源码篇幅较长,此处只取核心部分代码:
java
代码解读
复制代码
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException; import spring.aop.service.OriginServiceInterface; public final class $Proxy0 extends Proxy implements OriginServiceInterface { private static Method m3; public $Proxy0(InvocationHandler paramInvocationHandler) throws { super(paramInvocationHandler); } // 代理的源接口核心方法 public final void test() throws { try { // 调用构造代理对象传入的InvocationHandler接口实现类JdkDynamicAopProxy的invoke()方法 this.h.invoke(this, m3, null); return; } catch (Error|RuntimeException localError) { throw localError; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } static { try { m3 = Class.forName("spring.aop.service.OriginServiceInterface").getMethod("test", new Class[0]); return; } catch (NoSuchMethodException localNoSuchMethodException) { throw new NoSuchMethodError(localNoSuchMethodException.getMessage()); } catch (ClassNotFoundException localClassNotFoundException) { throw new NoClassDefFoundError(localClassNotFoundException.getMessage()); } } }
从上述源码中,我们可以看到,当代理对象调用代理方法时,内部会调用构造代理对象传入的InvocationHandler接口实现类JdkDynamicAopProxy的invoke()方法。
3.2.1.1 JdkDynamicAopProxy
JdkDynamicAopProxy作为Jdk动态代理生成的代理对象执行代理逻辑的入口拦截实现方法,其核心源码如下:
java
代码解读
复制代码
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object oldProxy = null; boolean setProxyContext = false; TargetSource targetSource = this.advised.targetSource; Object target = null; try { if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { // The target does not implement the equals(Object) method itself. return equals(args[0]); } else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // The target does not implement the hashCode() method itself. return hashCode(); } else if (method.getDeclaringClass() == DecoratingProxy.class) { // There is only getDecoratedClass() declared -> dispatch to proxy config. return AopProxyUtils.ultimateTargetClass(this.advised); } else if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { // Service invocations on ProxyConfig with the proxy config... return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } Object retVal; 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); // 构建拦截器链 // 针对PointcutAdvisor、IntroductionAdvisor类型的Advisor,此处会判断Advisor是否适用当前类 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); if (chain.isEmpty()) { // 如果不存在任何拦截器,则直接调用被代理对象的目标方法 Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else { // 构建拦截器链的方法调用入口MethodInvocation MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // 执行目标方法的拦截器链及目标方法 retVal = invocation.proceed(); } Class<?> returnType = method.getReturnType(); if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { // 如果是类似Build类方法,会返回对象自身,因此此处需换成代理对象 retVal = proxy; } else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) { throw new AopInvocationException( "Null return value from advice does not match primitive return type for: " + method); } return retVal; } // 省略部分代码... }
从上述源码中,可以看到程序员自定义的切面逻辑在此处与被代理对象的目标方法连接了起来,涉及到的核心类为MethodInvocation,对应实现为ReflectiveMethodInvocation
,由于CGLIB代理生成的代理对象也通过此类执行程序员自定义的切面逻辑,因此此类在最后进行分析。
3.2.2 CGLIB代理对象
由于CGLIB生成的代理对象源码篇幅很长,此处节选部分核心源码如下所示:
java
代码解读
复制代码
public class OriginService$$EnhancerBySpringCGLIB$$af89ebfe extends OriginService implements SpringProxy, Advised, Factory { private MethodInterceptor CGLIB$CALLBACK_0; public final void test() { MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0; if (methodInterceptor == null) { CGLIB$BIND_CALLBACKS(this); methodInterceptor = this.CGLIB$CALLBACK_0; } // 如果存在拦截器,则执行拦截器方法 // 此处实际对应的拦截器为DynamicAdvisedInterceptor if (methodInterceptor != null) { methodInterceptor.intercept(this, CGLIB$test$0$Method, CGLIB$emptyArgs, CGLIB$test$0$Proxy); } else { // 若不存在拦截器,则直接执行被代理对象的目标方法 super.test(); } } private static final void CGLIB$BIND_CALLBACKS(Object obj) { OriginService$$EnhancerBySpringCGLIB$$af89ebfe originService$$EnhancerBySpringCGLIB$$af89ebfe = (OriginService$$EnhancerBySpringCGLIB$$af89ebfe) obj; if (originService$$EnhancerBySpringCGLIB$$af89ebfe.CGLIB$BOUND) { return; } originService$$EnhancerBySpringCGLIB$$af89ebfe.CGLIB$BOUND = true; Object obj2 = CGLIB$THREAD_CALLBACKS.get(); if (obj2 == null) { obj2 = CGLIB$STATIC_CALLBACKS; if (obj2 == null) { return; } } MethodInterceptor[] methodInterceptorArr = (Callback[]) obj2; originService$$EnhancerBySpringCGLIB$$af89ebfe.CGLIB$CALLBACK_0 = methodInterceptorArr[0]; } }
从上述源码中,可以看到,对于代理的普通业务方法,代理对象将DynamicAdvisedInterceptor作为代理逻辑的入口,进行了代理逻辑及目标方法的执行调用。
3.2.2.1 DynamicAdvisedInterceptor
DynamicAdvisedInterceptor实现了MethodInterceptor接口,其实现的intercept()方法为代理逻辑的执行入口,其核心源码如下:
java
代码解读
复制代码
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); // 构建拦截器链 // 针对PointcutAdvisor、IntroductionAdvisor类型的Advisor,此处会判断Advisor是否适用当前类 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); Object retVal; if (chain.isEmpty() && CglibMethodInvocation.isMethodProxyCompatible(method)) { // 如果不存在任何拦截器,则直接执行被代理对象的目标方法 Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = invokeMethod(target, method, argsToUse, methodProxy); } else { // 构建拦截器链的方法调用入口MethodInvocation // 执行目标方法的拦截器链及目标方法 retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed(); } // 根据返回值类型处理返回值 retVal = processReturnType(proxy, target, method, retVal); return retVal; } // 省略部分代码... }
从上述源码中,可以看到,执行程序员自定义的切面逻辑核心入口为CglibMethodInvocation,此类继承了ReflectiveMethodInvocation,其调用的proceed()方法也是ReflectiveMethodInvocation实现的。
3.2.3 ReflectiveMethodInvocation
ReflectiveMethodInvocation作为代理逻辑执行的核心类,串联了程序员实现的切面逻辑与被代理对象的目标方法的顺序执行,其核心源码如下:
java
代码解读
复制代码
// 当前执行到的拦截器的索引 private int currentInterceptorIndex = -1; public Object proceed() throws Throwable { // 如果所有拦截器均已调用,则执行连接点,即被代理的目标方法 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); } // 拦截器索引+1,获取当前要执行的Advice Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { // 如果拦截器类型是InterceptorAndDynamicMethodMatcher,则动态匹配当前类是否满足当前条件 // 满足则执行当前拦截逻辑,否则继续获取下一个拦截器 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 { // 动态匹配失败,递归调用当前方法,获取下一个拦截器继续执行 return proceed(); } } else { // 若是普通拦截器,直接执行其拦截方法 return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } }
此处可以看到,通过递归的方式顺序调用了所有拦截器及目标方法,确保了所有内容的执行。 或许有人会存在疑问,此处并非所有分支逻辑都调用proceed()方法,其余分支如何保证执行逻辑的呢?我们可以选一个Advice的实现类AspectJAfterAdvice看一下具体逻辑,其核心源码如下:
java
代码解读
复制代码
public Object invoke(MethodInvocation mi) throws Throwable { try { // 先执行后续拦截器、目标方法 return mi.proceed(); } finally { // 执行拦截逻辑 invokeAdviceMethod(getJoinPointMatch(), null, null); } }
可以看到,在调用invoke()方法时,我们将当前ReflectiveMethodInvocation对象作为入参传入,并在内部调用了其proceed()方法,确保了递归逻辑的正常执行,并且通过栈的特性,在目标方法执行完成后,执行了这个After的拦截逻辑。
4.总结
通过前面的流程分析及源码分析,我们知道了Spring AOP的核心实现思想是动态代理,通过创建源对象的代理对象,并在代理对象代理的目标方法中,增加调用拦截,并将程序员实现的切面逻辑转换成为拦截器链,确保目标方法调用前、后的拦截逻辑能够正常执行。在Jdk动态代理中生成的代理对象,通过实现InvocationHandler接口的invoke()
方法实现的拦截逻辑;在CGLIB代理生成的代理对象,通过实现MethodInterceptor接口的invoke()
方法实现的拦截逻辑。\
整体的运行流程分为两部分:代理对象的创建、代理逻辑执行,整体步骤如下:
1.代理对象的创建
2.方法调用
3.执行通知
4.继续调用目标方法
5.返回结果
6.执行 After 通知
其中代理对象的创建会根据被代理对象是否实现了接口及是否配置了使用目标类进行代理对象创建来选择代理对象的创建方式。如果目标类未实现任何接口,则会使用Jdk动态代理类创建代理对象,否则选择CGLIB代理来创建对象。\
在执行代理逻辑的拦截器链过程中,通过利用方法栈递归的后入先出特性,保证了被代理方法执行前代理逻辑执行、被代理方法执行、被代理方法执行后代理逻辑执行的顺序
。