十.Spring源码剖析-拜托面试官别再问我AOP原理了

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: IOC/DI , AOP 是Spring最重要的两个特性 ,也是面试高频被问到的部分,前面我们已经分析了Spring的IOC相关源码以及DI依赖注入相关源码,从本篇文章开始我们着手分析Spring的AOP源码 。开始之前,你需要对AOP 原理,JDK动态代理,CGLIB动态代理有一定的理解。这里先上一个图,后面源码分析的时候可以看着图来

目录

@[toc]

前言

IOC/DI , AOP 是Spring最重要的两个特性 ,也是面试高频被问到的部分,前面我们已经分析了Spring的IOC相关源码以及DI依赖注入相关源码,从本篇文章开始我们着手分析Spring的AOP源码 。

开始之前,你需要对AOP 原理,JDK动态代理,CGLIB动态代理有一定的理解。这里先上一个图,后面源码分析的时候可以看着图来

在这里插入图片描述

AOP的理解

AOP基本概念

AOP是为面向切面编程,为什么要面向切面,何为切面?我们知道对于OOP面向对象而言在某些开发场景中是有一定不足,由于面向对象的思想是纵向的,它面对的是一个一个的对象,当我们需要在多个类中引入同一个公共的业务时(比如:事务,操作日志等),那么在每个类中都要引入公共的业务代码,从而造成代码大量重复,代码结构不优雅,不方便维护 ,这个时候就需要使用到面向切面的编程来解决这个问题。使用AOP可以把分散在多个类中的公共的代码剥离出来,和业务本身的代码解耦, 然后通过动态代理将公共业务代码作用到多个对象,代码结构也更加优雅。

所以可以认为 面向切面 是对 面向对象 的补充,它的思想是横向的,它面向的是一个切面,如果把一个对象看做一个点,那么多个对象就是一个面,是为切面,AOP多用于:事务,日志,监控,流控等等业务场景。
在这里插入图片描述

AOP实现原理

AOP的实现原理是基于动态代理,动态代理就是在运行时期动态的为某个类(原生类)生成代理类以达到代码增强的目的,且代理类是持有原生类的,可以在代理类中调用原生类以及做一些增强业务。

动态代理分为JDK动态代理和CGLIB代理,CGLIB代理需要导入相关的jar包。两者的区别是JDK动态代理要求原始类(被代理类)需要实现至少一个接口。而CGLIB则是基于继承进行代理,原生类可以不实现任何接口。

对于Spring而言默认采用JDK动态代理,如果原生类没有实现任何接口,Spring会选择CGLIB代理,或者你可以通过配置文件强制指定使用CGLIB代理。

AOP案例

下面我们使用AOP来做一个事务管理案例:在每个Service方法执行前后添加事务的代码

1.创建一个普通类,这个类的方法需要有事务

@Service
public class UserServiceImpl implements IUserService {
   
   

    public void insert() {
   
   
        System.out.println("UserServiceImpl.insert:保存User...");
    }

    public void delete() {
   
   
        System.out.println("UserServiceImpl.delete:删除User");
    }
}

2.创建一个切面类,这个类里面提供公共的业务代码,即:事务代码

@Component
@Aspect
public class TranscationManager {
   
   

    //定义切点,表达式作用于所有到service的所有的方法
    @Pointcut("execution(* cn.xxx.*.service.*.*(..))")
    public void pointcut(){
   
   }

    //前置通知 , 方法执行前执行,用来开启事务
    @Before("pointcut()")
    public void begin(JoinPoint joinPoint){
   
   

        System.out.println("TranscationManager.begin:开启事务...:");
    }
    //后置返回通知 ,方法正常返回后执行, 用来提交事务
    @AfterReturning("pointcut()")
    public void commit(){
   
   
        System.out.println("TranscationManager.commit:提交事物...");
    }

    //异常通知,方法出现异常调用,用来回滚事务
    @AfterThrowing(value = "pointcut()",throwing="e")
    public void rollback(JoinPoint joinPoint,Throwable e){
   
   
        System.out.println("TranscationManager.rollback:回滚事物咯...:"+e.getMessage());
    }

    //最终通知,不管方法会不会出现异常,都会执行,用来关闭资源
    @After("pointcut()")
    public void close(){
   
   
        System.out.println("TranscationManager.close:关闭连接...");
    }


    //环绕通知,拦截原始类的类的方法,可以通过 joinPoint调用原始的类
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint){
   
   


        return null;
    }

}

3.配置Spring支持AOP注解

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
       http://www.springframework.org/schema/aop   http://www.springframework.org/schema/aop/spring-aop.xsd
       http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <!--开启IOC注解支持-->
    <context:component-scan base-package="cn.xx" />

    <!--开启AOP注解支持,默认使用jdk动态代理,如果指定 proxy-target-class=true 则实例CGLIB代理-->
    <aop:aspectj-autoproxy />

</beans>

4.测试代码

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:application_aop.xml")
public class AopTest {
   
   

    @Autowired
    private IUserService userService ;

    @Test
    public void testAop(){
   
   
        userService.insert();
        System.out.println("======================================");
        userService.delete();
    }
}

控制台效果

TranscationManager.begin:开启事务...:
UserServiceImpl.insert:保存User...
TranscationManager.commit:提交事物...

TranscationManager.close:关闭连接...

TranscationManager.begin:开启事务...:
UserServiceImpl.delete:删除User...
TranscationManager.commit:提交事物...
TranscationManager.close:关闭连接...

这里我们看到了,使用AOP可以把公共的代码剥离出去和业务变身代码解耦,同时也方便扩展。

怎么理解这个AOP案例,首先要明白需求:在多个service方法执行前,否 或 出现异常做出相应的事务处理。我们把UserService看着原生类, 把TranscationManager 切面看着是增强代码,那么Spring是如何做到把 TranscationManager 的增强逻辑 加入到 UserService的方法前后的呢?

  1. 找到所有原生类(被代理类):我们在 TranscationManager中定义了一个切点:@Pointcut("execution(* cn.xxx.*.service.*.*(..))") :这切点定义了一个表达式,这个表达式的含义就是找到cn.xxx包下所有的service的所有方法,Spring就知道了需要拦截这些方法的执行。
  2. 找到了service的方法,如何在方法前,后做事情?我们在TranscationManager中定义了@Before("pointcut()") 前置通知,@AfterReturning("pointcut()")后置通知等,当我们调用userService的方法之前就会触发 Before 前置通知中的逻辑 ,方法执行完成就会触发 AfterReturning 后置通知的逻辑,异常通知和最终通知也是一个道理。
  3. 实现原理就是动态代理,其实Spring为所有切点切到的类都生成了代理类,也就是说在test类中注入的 @Autowired private IUserService userService ; 其实并不是我们写的那个UserService,而是基于UserService代理出来的一个代理类。代理类持有原生类,且代理类和原生类有相同的方法,所以你感觉你在调用UserService,其实在调用代理类。

    在代理类中的方法对原生类方法做了增强 ,而增强的逻辑就是 TranscationManager 中的逻辑,比如调用userService.insert 实则进入了代理类的insert方法,方法中先调用TranscationManager@Before 前置通知业务,然后调用原生类的insert,方法结尾调用TranscationManager@AfterReturning 后置通知,出现异常调用TranscationManager@AfterThrowing异常通知等等。这样是不是就达到了上面的增强效果了。

如果没有去研究过JDK动态代理和CGLIB代理可能你看起来比较晕,对于Spring切面的东西这里不做太多解释了,不是本篇主要内容,下面我就对于这个AOP案例做源码分析。

AOP解析器

在上面的案例中我们通过 配置来开启AOP支持,稍微动动脑袋能想到Spring一定会有一个类来处理该配置。 在Spring中有一个接口叫 NamespaceHandlerSupport ,它提供了Spring配置文件的namespace的解析支持。
在这里插入图片描述
其中有一个实现叫 AopNamespaceHandler , 它是针对于 <aop: 开头的namespace 解析支持,看一下这个类的源码

AOP解析器:AspectJAutoProxyBeanDefinitionParser

//aop命名空间的NamespaceHandler 。
//为<aop:config>标签提供一个BeanDefinitionParser 。 config标签可以包括嵌套的pointcut 、 advisor和aspect标签。
public class AopNamespaceHandler extends NamespaceHandlerSupport {
   
   

    /**
     * Register the {@link BeanDefinitionParser BeanDefinitionParsers} for the
     * '{@code config}', '{@code spring-configured}', '{@code aspectj-autoproxy}'
     * and '{@code scoped-proxy}' tags.
     */
    @Override
    public void init() {
   
   
        // In 2.0 XSD as well as in 2.5+ XSDs
        //<aop:config 解析器
        registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
        //【主角在这里】注册针对于<aop:aspectj-autoproxy 的解析器 AspectJAutoProxyBeanDefinitionParser
        registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
        registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());

        // Only in 2.0 XSD: moved to context namespace in 2.5+
        registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
    }

}

到这里我们看到了针对于 <aop:aspectj-autoproxy 的解析器 AspectJAutoProxyBeanDefinitionParser,它实现了BeanDefinitionParser,解析逻辑都在parse方法中,源码如下:

class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {
   
   

    //Element就是 <aop:aspectj-autoproxy 元素的封装
    @Override
    @Nullable
    public BeanDefinition parse(Element element, ParserContext parserContext) {
   
   
        //注册一个 AspectJAnnotationAutoProxyCreator
        //用于处理当前应用程序上下文中的所有 AspectJ 切面,以及 Spring Advisor。
        AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
        //处理子节点
        extendBeanDefinition(element, parserContext);
        return null;
    }

    ...省略...

}

该方法的作用主要是注册了一个 AspectJAnnotationAutoProxyCreator 自动代理创建器,它的作用就是用来处理Aop。 AspectJAutoProxyBeanDefinitionParser 的 parse 方法是在IOC启动过程中,通过DefaultBeanDefinitionDocumentReader#parseBeanDefinitions 委派 BeanDefinitionParserDelegate#parseCustomElement去解析的。

注册AnnotationAwareAspectJAutoProxyCreator

parse方法中比较重要的就是 AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary , 它创建了一个 AnnotationAwareAspectJAutoProxyCreator 代理自动创建器 ,AOP的功能重要就是通过它来完成的,它可以根据 Point 解定义的切点来自动代理相匹配的 bean,跟一下该方法源码:

public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
            ParserContext parserContext, Element sourceElement) {
   
   
        //【重要】通过BeanDefinitionRegistry注册一个 AnnotationAwareAspectJAutoProxyCreator
        BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
                parserContext.getRegistry(), parserContext.extractSource(sourceElement));

        //对 proxy-target-class 和 expose-proxy 属性处理
        useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
        //注册组件 把 beanDefinition 注册到ParserContext上下文中
        registerComponentIfNecessary(beanDefinition, parserContext);
    }

该方法做了三件事情

  • 通过BeanDefinitionRegistry注册一个 AnnotationAwareAspectJAutoProxyCreator ,该类是AspectJ 切面处理类
  • 对 proxy-target-class 和 expose-proxy 属性处理 ,就是把BeanDefinition中的proxyTargetClass和exposeProxy属性设置为true
  • 这次组件, 把AnnotationAwareAspectJAutoProxyCreator 的 beanDefinition 注册到ParserContext上下文中

我们继续跟踪注册AnnotationAwareAspectJAutoProxyCreator 的代码:AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary

    @Nullable
    public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,
            @Nullable Object source) {
   
   

        return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
    }

    //BeanDefinitionRegistry:bean的注册器
    //cls:AnnotationAwareAspectJAutoProxyCreator的类型
    @Nullable
    private static BeanDefinition registerOrEscalateApcAsRequired(
            Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
   
   

        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        //如果容器中已经包含了 org.springframework.aop.config.internalAutoProxyCreator 自动代理创建者的BeanDefinition
        if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
   
   
            //获取BeanDefinition
            BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
            //class比较
            if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
   
   
                //如果已经有自动创建器了,按照优先级比较选择使用哪一个
                int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
                int requiredPriority = findPriorityForClass(cls);
                if (currentPriority < requiredPriority) {
   
   
                    apcDefinition.setBeanClassName(cls.getName());
                }
            }
            return null;
        }
        //如果容器中还没有注册自动创建器,就注册一个
        RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
        beanDefinition.setSource(source);
        beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
        beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        //通过BeanDefinitionRegistry注册一个 代理自动创建器
        registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
        return beanDefinition;
    }

方法会判断容器中如果已经注册了 自动代理创建器,则按照优先级选择使用哪个,如果么有注册就使用BeanDefinitionRegistry注册一个。

处理proxy-target-class和ExposeProxy

proxy-target-class 的对于 属性的处理,该属性的作用是指定代理的方式为CGLIB。

//对 proxy-target-class 和 expose-proxy 属性处理
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) {
   
   
    if (sourceElement != null) {
   
   
        //获取  <aop:aspectj-autoproxy proxy-target-class="" />  proxy-target-class 属性
        boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
        if (proxyTargetClass) {
   
   
            //如果proxyTargetClass=true,则使用CGLIB代理
            //definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
            //把 definition 中的 proxyTargetClass设置为true
            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
        }
        //当exposeProxy为true时暴露代理对象,会把proxy动态代理对象设置到AopContext上下文中
        boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
        if (exposeProxy) {
   
   
            //definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
            //把 definition 中的 exposeProxy 设置为true
            AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
        }
    }
}

这里做了两个事情

  • 根据配置: 将 definition 中的 proxyTargetClass设置为true ,生成代理将会使用CGLIB方式,否则默认使用JDK动态代理
  • 根据配置: 将 definition 中的 exposeProxy设置为true ,目的是把创建的代理对象添加到AopContext上下文中,为什么要这麽做?如果有如下代码:

      public class AServiceImpl implements AService{
         
         
          @Transactional
          public void a(){
         
         
              this.b();
          }
          @Transactional(propagation = Propagation.REQUIRES_NEW)
          public void b(){
         
         
          }
      }
    

    这里的 this 是原生类,并不是代理类,也就意味这b的 @Transactional(propagation = Propagation.REQUIRES_NEW)
    事务增强代码是不会执行的,对于这个问题我们可以做如下处理

    1. 修改配置:
    2. this.b() 修改为:((AService)AopContext.currentProxy()).b(); 得到代理类执行b()方法

      增强器

      上面的一个大堆流程主要是创建了一个 AnnotationAwareAspectJAutoProxyCreator ,那么它是如何来处理AOP的呢?看一下它的继承体系
      在这里插入图片描述
      AnnotationAwareAspectJAutoProxyCreator是一个BeanPostProcessor,当Spring实例化这个Bean时会在这个Bean的initMethod初始化之后调用postProcessAfterInitialization方法,Aop的实现就在这里开始。AbstractAutoProxyCreator#postProcessAfterInitialization源码如下:
      ```java

      • Create a proxy with the configured interceptors if the bean is
      • identified as one to proxy by the subclass.
      • @see #getAdvicesAndAdvisorsForBean
        */
        //如果 bean 被子类标识为代理,则使用配置的拦截器创建一个代理。
        @Override
        public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
        if (bean != null) {
         //根据Bean的class和name,创建一个缓存的key  ,
         Object cacheKey = getCacheKey(bean.getClass(), beanName);
         if (!this.earlyProxyReferences.contains(cacheKey)) {
             //对适合代理的Bean进行封装
             return wrapIfNecessary(bean, beanName, cacheKey);
         }
        
        }
        return bean;
        }
//创建代理
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    //如果已经处理过,就直接返回Bean
    if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
        return bean;
    }
    //不需要增强
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    }
    //是基础设施类(比如 Pointcut.class,Aspect.class等基础类不需要代理),
    // 或者是原始类不做代理,比如 beanName以 .ORIGINAL 结尾就会跳过代理
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

    // Create proxy if we have advice.
    //获取增强,即:获取到上面案例中的TranscationManager中的增强方法,封装成一个一个,InstantiationModelAwarePointcutAdvisorImpl,该类可以是对切面方法的封装
    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));
        //把代理的type放入proxyTypes
        this.proxyTypes.put(cacheKey, proxy.getClass());
        return proxy;
    }
    //缓存的key放入advisedBeans
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
}
方法中先判断了Bean是否需要创建代理,比如当前bean是Aspect,pintcut等基础设施类就不需要代理,然后调用 getAdvicesAndAdvisorsForBean 获取到增强器 ,最后 调用createProxy方法创建代理对象。

## 获取增强器
获取增强器是在 `AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean`中完成的 ,我们来一步步跟踪一下它的获取流程
```java

    //[第一步] 找到增强器
    @Override
    @Nullable
    protected Object[] getAdvicesAndAdvisorsForBean(
            Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
        //找打增强器,提取成Advisor
        List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
        if (advisors.isEmpty()) {
            return DO_NOT_PROXY;
        }
        return advisors.toArray();
    }

    //[第二步]  找到所有增强器,以及找到bean适用的增强器
    protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
        //找到所有增强方法
        List<Advisor> candidateAdvisors = findCandidateAdvisors();
        //找到当前bean适用的增强方法
        List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
        extendAdvisors(eligibleAdvisors);
        if (!eligibleAdvisors.isEmpty()) {
            eligibleAdvisors = sortAdvisors(eligibleAdvisors);
        }
        return eligibleAdvisors;
    }

上面逻辑做了两件事情, 找到所有增强器,以及找到bean适用的增强器,查找所有增强器在 AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors中完成的,源码如下:

@Override
    protected List<Advisor> findCandidateAdvisors() {
   
   
        // Add all the Spring advisors found according to superclass rules.
        //调用父类,查找所有的增强方法
        List<Advisor> advisors = super.findCandidateAdvisors();
        // Build Advisors for all AspectJ aspects in the bean factory.
        if (this.aspectJAdvisorsBuilder != null) {
   
   
        //调用 aspectJAdvisorsBuilder.buildAspectJAdvisors 构建增强器
            advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
        }
        return advisors;
    }

这里主要通过 aspectJAdvisorsBuilder 去查找增强器,然后添加到advisors集合中返回。

public List<Advisor> buildAspectJAdvisors() {
   
   
        //得到切面类
        List<String> aspectNames = this.aspectBeanNames;

        if (aspectNames == null) {
   
   
            synchronized (this) {
   
   
                aspectNames = this.aspectBeanNames;
                if (aspectNames == null) {
   
   
                    List<Advisor> advisors = new LinkedList<>();
                    aspectNames = new LinkedList<>();
                    //获取到spring中所有的beanNames
                    String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                            this.beanFactory, Object.class, true, false);
                    for (String beanName : beanNames) {
   
   
                        //循环BeanName 获取增强方法
                        if (!isEligibleBean(beanName)) {
   
   
                        //不合法的Bean跳过
                            continue;
                        }
                        // We must be careful not to instantiate beans eagerly as in this case they
                        // would be cached by the Spring container but would not have been weaved.
                        //根据名字得到类型
                        Class<?> beanType = this.beanFactory.getType(beanName);
                        if (beanType == null) {
   
   
                            continue;
                        }
                        //是否是切面类,有aspect注解,不是切面不做处理
                        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);
                                //查找增强方法,前置,后置,异常,最终通知
                                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;
                }
            }
        }

        if (aspectNames.isEmpty()) {
   
   
            return Collections.emptyList();
        }
        List<Advisor> advisors = new LinkedList<>();
        //找到所有切面类
        for (String aspectName : aspectNames) {
   
   
            //获取切面类的增强方法
            List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
            if (cachedAdvisors != null) {
   
   
                advisors.addAll(cachedAdvisors);
            }
            else {
   
   
                MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
                advisors.addAll(this.advisorFactory.getAdvisors(factory));
            }
        }
        //返回增强器
        return advisors;
    }

上面方法会先得到切面类 aspectNames,然后根据切面类从 advisorsCache缓存中得到增强方法并返回。

解析切面中的增强方法

当然如果还没有切面和增强方法,就会先从容器中得到所有的BeanName循环得到class,通过判断是否有aspect注解来得到切面。得到切面后,通过this.advisorFactory.getAdvisors(factory)提取切面中的增强方法,并缓存到advisorsCache map中。下面是 ReflectiveAspectJAdvisorFactory#getAdvisors 源码

@Override
    public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
   
   
        //获取切面类
        Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
        //获取切面名字
        String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
        //校验切面类
        validate(aspectClass);

        // We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
        // so that it will only instantiate once.
        MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
                new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

        List<Advisor> advisors = new LinkedList<>();
        //使用反射工具, ReflectionUtils#doWithMethods 获取切面类的所有方法
        for (Method method : getAdvisorMethods(aspectClass)) {
   
   
            //提取增强方法 , 把 method 提出成 Advisor【重要】
            Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
            if (advisor != null) {
   
   
                advisors.add(advisor);
            }
        }

        // If it's a per target aspect, emit the dummy instantiating aspect.
        if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
   
   
            Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
            advisors.add(0, instantiationAdvisor);
        }

        // Find introduction fields.
        for (Field field : aspectClass.getDeclaredFields()) {
   
   
            Advisor advisor = getDeclareParentsAdvisor(field);
            if (advisor != null) {
   
   
                advisors.add(advisor);
            }
        }

        return advisors;
    }

上面业务中通过 getAdvisorMethods(aspectClass) 获取切面类所有的方法,底层通过ReflectionUtils#doWithMethods 反射实现。 然后调用 ReflectiveAspectJAdvisorFactory#getAdvisor 提取出切面中的增强器 Advisor(对增强方法的封装)。重点看一下 getAdvisor 源码

@Override
    @Nullable
    public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
            int declarationOrderInAspect, String aspectName) {
   
   
        //验证
        validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
        //获取切点信息,其实就是获取注解表达式获取如:@Before("point()")
        AspectJExpressionPointcut expressionPointcut = getPointcut(
                candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
        if (expressionPointcut == null) {
   
   
            return null;
        }
        //根据切点信息生成增强器
        //把切面的增强方法提取成一个一个的  Advisor,
        //由Advisor的实现类InstantiationModelAwarePointcutAdvisorImpl 进行统一封装 
        return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
                this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
    }

==============================================================================================
        //获取切点信息,其实就是获取注解表达式获取如:@Before("point()")
    @Nullable
    private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
   
   
        //【第一步】找到方法上的注解
        AspectJAnnotation<?> aspectJAnnotation =
                AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
        if (aspectJAnnotation == null) {
   
   
            return null;
        }

        AspectJExpressionPointcut ajexp =
                new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
        //【第二步】得到注解表达式:如:pointcut()或者 @Pointcut(" execution(...)")
        //封装到AspectJExpressionPointcut对象
        ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
        if (this.beanFactory != null) {
   
   
            ajexp.setBeanFactory(this.beanFactory);
        }
        return ajexp;
    }
===============================================================================================

    //找到切面注解
    @SuppressWarnings("unchecked")
    @Nullable
    protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
   
   
        //就是要找这些注解
        Class<?>[] classesToLookFor = new Class<?>[] {
   
   
                Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};
        for (Class<?> c : classesToLookFor) {
   
   
            //找到指定方法的注解,封装成AspectJAnnotation
            AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) c);
            if (foundAnnotation != null) {
   
   
                return foundAnnotation;
            }
        }
        return null;
    }

在上面逻辑中,把切面的增强方法提取成一个一个的 Advisor,由Advisor的实现类InstantiationModelAwarePointcutAdvisorImpl 进行统一封装 ,源码如下:

public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
            Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
            MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
   
   
        //切入点
        this.declaredPointcut = declaredPointcut;
        //切面类的类型
        this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
        //增强的方法名
        this.methodName = aspectJAdviceMethod.getName();
        //方法的参数
        this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
        //
        this.aspectJAdviceMethod = aspectJAdviceMethod;
        this.aspectJAdvisorFactory = aspectJAdvisorFactory;
        this.aspectInstanceFactory = aspectInstanceFactory;
        this.declarationOrder = declarationOrder;
        this.aspectName = aspectName;

        if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
   
   
            // Static part of the pointcut is a lazy type.
            Pointcut preInstantiationPointcut = Pointcuts.union(
                    aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);

            // Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
            // If it's not a dynamic pointcut, it may be optimized out
            // by the Spring AOP infrastructure after the first evaluation.
            this.pointcut = new PerTargetInstantiationModelPointcut(
                    this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
            this.lazy = true;
        }
        else {
   
   
            // A singleton aspect.
            this.pointcut = this.declaredPointcut;
            this.lazy = false;
            //实例化 增强器
            this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
        }
    }

上面构造方法是把增强方法相关的信息进行了赋值,最后调用了一个 instantiateAdvice 来对增强器进行初始化,不同的增强逻辑不同,比如Before,After 他们的增强前置是不同的,所以需要不同的增强器来完成不同的逻辑,见:instantiateAdvice 方法源码

创建增强器

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);
    }

@Override
    @Nullable
    public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
            MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
   
   
        //切面类
        Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
        //验证
        validate(candidateAspectClass);
        //找到增强方法的注解封装
        AspectJAnnotation<?> aspectJAnnotation =
                AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
        if (aspectJAnnotation == null) {
   
   
            return null;
        }

        // If we get here, we know we have an AspectJ method.
        // Check that it's an AspectJ-annotated class
        //判断class是否是切面
        if (!isAspect(candidateAspectClass)) {
   
   
            throw new AopConfigException("Advice must be declared inside an aspect type: " +
                    "Offending method '" + candidateAdviceMethod + "' in class [" +
                    candidateAspectClass.getName() + "]");
        }

        if (logger.isDebugEnabled()) {
   
   
            logger.debug("Found AspectJ method: " + candidateAdviceMethod);
        }

        AbstractAspectJAdvice springAdvice;
        //不同的增强做出不同的处理,创建了不同的 Advice
        switch (aspectJAnnotation.getAnnotationType()) {
   
   
            case AtBefore:
            //前置AspectJMethodBeforeAdvice
                springAdvice = new AspectJMethodBeforeAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                break;
            case AtAfter:
            //最终通知
                springAdvice = new AspectJAfterAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                break;
            case AtAfterReturning:
                //后置通知
                springAdvice = new AspectJAfterReturningAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
                if (StringUtils.hasText(afterReturningAnnotation.returning())) {
   
   
                    springAdvice.setReturningName(afterReturningAnnotation.returning());
                }
                break;
            case AtAfterThrowing:
                //异常通知
                springAdvice = new AspectJAfterThrowingAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
                if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
   
   
                    springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
                }
                break;
            case AtAround:
                //环绕通知
                springAdvice = new AspectJAroundAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                break;
            case AtPointcut:
                //切点
                if (logger.isDebugEnabled()) {
   
   
                    logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
                }
                return null;
            default:
                throw new UnsupportedOperationException(
                        "Unsupported advice type on method: " + candidateAdviceMethod);
        }

        // Now to configure the advice...
        springAdvice.setAspectName(aspectName);
        springAdvice.setDeclarationOrder(declarationOrder);
        //给增强器设置参数
        String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
        if (argNames != null) {
   
   
            springAdvice.setArgumentNamesFromStringArray(argNames);
        }
        springAdvice.calculateArgumentBindings();

        return springAdvice;
    }

这里根据不同的增强注解生成不同的增强器,比如 AtBefore 会对应 AspectJMethodBeforeAdvice ,比如 AtAfter 对应了 AspectJAfterAdvice。增强器中都提供了一个 invoke 来调用增强方法。如AspectJMethodBeforeAdvice

public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements MethodBeforeAdvice, Serializable {
   
   

    public AspectJMethodBeforeAdvice(
            Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
   
   

        super(aspectJBeforeAdviceMethod, pointcut, aif);
    }


    @Override
    public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {
   
   
        //调用增强方法,即调用@Before注解的前置通知方法
        invokeAdviceMethod(getJoinPointMatch(), null, null);
    }

    @Override
    public boolean isBeforeAdvice() {
   
   
        return true;
    }

    @Override
    public boolean isAfterAdvice() {
   
   
        return false;
    }

}

增强器的调用

这里有个疑问,上面已经针对不同的注解生成了不同的增强器,那么这些增强器在什么时候调用呢?当然是在我们调用对象的方法的时候,触发前置,后置等增强。在Spring内部有一个 MethodBeforeAdviceInterceptor 拦截器,该拦截器会在创建Bean的代理的时候被创建,它的作用就是在方法调用前拦截,我们看一下源码:

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
   
   

    private MethodBeforeAdvice advice;


    /**
     * Create a new MethodBeforeAdviceInterceptor for the given advice.
     * @param advice the MethodBeforeAdvice to wrap
     */
    public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
   
   

        Assert.notNull(advice, "Advice must not be null");    
        //前置增强器
        this.advice = advice;
    }

    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
   
   
        //调用方法前:调用前置增强器中的增强
        this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
        //调用方法
        return mi.proceed();
    }

}

对于后置增强没有Interceptor ,而是在拦截器链中直接调用 AspectJAfterAdvice

public class AspectJAfterAdvice extends AbstractAspectJAdvice
        implements MethodInterceptor, AfterAdvice, Serializable {
   
   

    public AspectJAfterAdvice(
            Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
   
   

        super(aspectJBeforeAdviceMethod, pointcut, aif);
    }


    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
   
   
        try {
   
   
            return mi.proceed();
        }
        finally {
   
   
            //调用后置增强
            invokeAdviceMethod(getJoinPointMatch(), null, null);
        }
    }

    @Override
    public boolean isBeforeAdvice() {
   
   
        return false;
    }

    @Override
    public boolean isAfterAdvice() {
   
   
        return true;
    }

}

其他的增强这里就不一一分析了 , 到这里我们基本上把增强器的解析流程分析完成了。

选择适用的增强器

在上面分析中已经找到了所有增强,但是不是所有增强器都适合,所以会过滤出适用的增强,主要实现在AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply,其实就是找到满足我们配置的 切入点 的增强器,具体的细节这里就进去分析了。

创建代理

上面流程走完,找到了适合当前Bean的增强器,然后就会为当前Bean创建代理了,通过AbstractAutoProxyCreator#createProxy 完成

代理创建器:AbstractAutoProxyCreator

protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
            @Nullable Object[] specificInterceptors, TargetSource targetSource) {
   
   

        if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
   
   
            AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
        }
        //创建ProxyFactory
        ProxyFactory proxyFactory = new ProxyFactory();
        //拷贝当前类的属性
        proxyFactory.copyFrom(this);
        //判断是基于接口的代理,就是判断 <aop:aspectj-autoproxy proxy-target-class="false" 属性
        //默认fasle,即:走JDK动态代理
        if (!proxyFactory.isProxyTargetClass()) {
   
   
            //确定给定的 bean 是否应该用它的目标类而不是它的接口来代理。
            if (shouldProxyTargetClass(beanClass, beanName)) {
   
   
                proxyFactory.setProxyTargetClass(true);
            }
            else {
   
   
                //找到被代理类的接口interface ,添加到到 proxyFactory 代理工厂中
                evaluateProxyInterfaces(beanClass, proxyFactory);
            }
        }

        Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
        //给代理工厂加入增强器
        proxyFactory.addAdvisors(advisors);
        //设置被代理类
        proxyFactory.setTargetSource(targetSource);
        //定制代理,是个空方法,可以进行扩展
        customizeProxyFactory(proxyFactory);

        //当配置被冻结时,不能进行任何建议更改。
        proxyFactory.setFrozen(this.freezeProxy);
        if (advisorsPreFiltered()) {
   
   
            proxyFactory.setPreFiltered(true);
        }
        //通过 ProxyFactory 创建代理
        return proxyFactory.getProxy(getProxyClassLoader());
    }

看得出这个方法在配置代理工厂,ProxyFactory,配置好之后通过代理工厂创建代理。方法做了如下事情

  • 把当前类中的属性添加到工厂
  • 把被代理的接口添加到工厂
  • 把增强器添加到工厂
  • 把要代理的原始类添加到工厂
  • 创建代理

该方法中通过判断 proxy-target-class="false" 来决定采用JDK动态代理或者CGLIB代理,之前有分析过

  • 如果被代理类有接口,Spring默认使用JDK动态代理
  • 如果被代理类有接口,可以配置 proxy-target-class="true" 强制使用CGLIB代理
  • 如果被代理类没有接口,只能选择CGLIB代理 ,因为JDK动态代理只是支持有有接口的类,CGLIB是为被代理类生成一个子类,复写其所有方法来达到增强,CGLIB代理需要引入CGLIB库

继续跟进 proxyFactory.getProxy 方法

public Object getProxy(@Nullable ClassLoader classLoader) {
   
   
        //先创建一个JDKDynamicAopProxy  , 然后创建代理类
        return createAopProxy().getProxy(classLoader);
    }


-----------------------------------------------------------------------------------------------

    @Override
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
   
   
        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.");
            }
            //判断目标是否有接口,选择使用JdkDynamicAopProxy创建代理,否则使用CGLIB
            if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
   
   
                return new JdkDynamicAopProxy(config);
            }
            //使用ObjenesisCglibAopProxy创建代理
            return new ObjenesisCglibAopProxy(config);
        }
        else {
   
   
            return new JdkDynamicAopProxy(config);
        }
    }

ProxyFactory#getProxy 首先会创建一个AopProxy 代理创建器,根据目标类是否有接口来选择使用JDK代理:JdkDynamicAopProxy 和CGLIB代理:ObjenesisCglibAopProxy。然后调用getProxy方法创建代理。

JDK动态代理:JDKDynamicAopProxy

JdkDynamicAopProxy 实现了 InvocationHandler,InvocationHandler是JDK动态代理最核心的一个类,代理对象的方法调用都会被委托到 invoke 方法中去执行,JdkDynamicAopProxy#getProxy 源码如下:

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
   
   

    //创建代理
    @Override
    public Object getProxy(@Nullable ClassLoader classLoader) {
   
   
        if (logger.isDebugEnabled()) {
   
   
            logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
        }
        Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
        findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
        //创建代理类
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }


    //...省略代码...
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
   
   
        //方法调用
        MethodInvocation invocation;
        Object oldProxy = null;
        boolean setProxyContext = false;

        TargetSource targetSource = this.advised.targetSource;
        Object target = null;

        try {
   
   
            // 如果是equals方法:目标类本身没有实现 equals(Object) 方法。
            if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
   
   
                // The target does not implement the equals(Object) method itself.
                return equals(args[0]);
            }
            //如果是hashCode方法:目标类本身没有实现 hashCode() 方法。
            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);
            }
            //调用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);

            // Get the interception chain for this method.
            //获取此方法的拦截器通知链
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

            // Check whether we have any advice. If we don't, we can fallback on direct
            // reflective invocation of the target, and avoid creating a MethodInvocation.
            if (chain.isEmpty()) {
   
   
            //如果没有拦截器能应用到该方法,直接反射调用方法
                // 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 = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
            }
            else {
   
   
                //创建 ReflectiveMethodInvocation 方法调用
                // We need to create a method invocation...
                invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                // Proceed to the joinpoint through the interceptor chain.
                //通过拦截器链进入连接点
                retVal = invocation.proceed();
            }

            // Massage return value if necessary.
            Class<?> returnType = method.getReturnType();
            if (retVal != null && retVal == target &&
                    returnType != Object.class && returnType.isInstance(proxy) &&
                    !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
   
   
                // Special case: it returned "this" and the return type of the method
                // is type-compatible. Note that we can't help if the target sets
                // a reference to itself in another returned object.
                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;
        }
        finally {
   
   
            if (target != null && !targetSource.isStatic()) {
   
   
                // Must have come from TargetSource.
                targetSource.releaseTarget(target);
            }
            if (setProxyContext) {
   
   
                // Restore old proxy.
                AopContext.setCurrentProxy(oldProxy);
            }
        }
    }
}

invoke方法中首先获取方法的拦截器通知链,如果有就会创建 MethodInvocation来调用方法,应用通知,如果没有拦截器链就直接反射调用方法。

方法增强拦截器:advice的织入

拦截器通知链是通过getInterceptorsAndDynamicInterceptionAdvice得到的:

    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;
    }
-----------------------------------------------
    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.
        //用来装拦截器
        List<Object> interceptorList = new ArrayList<>(config.getAdvisors().length);
        Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
        boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
        //注册一系列 AdvisorAdapter,用于将 Advisor 转化成 MethodInterceptor
        AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();

        for (Advisor advisor : config.getAdvisors()) {
   
   
            if (advisor instanceof PointcutAdvisor) {
   
   
                // Add it conditionally.
                PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
                if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
   
   
                //把advisor转换成MethodInterceptor
                    MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
                    //检查当前 advisor 的 pointcut 是否可以匹配当前方法
                    MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                    if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
   
   
                        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
                                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;
    }

getInterceptorsAndDynamicInterceptionAdvice这个方法主要是把Advisor 转成 MethodInterceptor , 也就是说Advisor可以应用到连接点,也就是当代理对象方法被调用时就可以触发相应的 Advisor 通知了。

在AOP中为各种通知封装了不同的拦截器,在上面代码中出现一个注册器:GlobalAdvisorAdapterRegistry 其中委托AdvisorAdapterRegistry 来实现增强拦截器的注册,默认实现类是DefaultAdvisorAdapterRegistry 代码如下:

public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
   
   

    private final List<AdvisorAdapter> adapters = new ArrayList<>(3);


    /**
     * Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters.
     * 创建一个注册器,用来注册各种适配器
     */
    public DefaultAdvisorAdapterRegistry() {
   
   
        //方法前置通知适配器
        registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
        //后置通知适配器
        registerAdvisorAdapter(new AfterReturningAdviceAdapter());
        //异常通知适配器
        registerAdvisorAdapter(new ThrowsAdviceAdapter());
    }

    //把advice 通知 包裹成 Advisor 增强器
    @Override
    public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
   
   
        if (adviceObject instanceof Advisor) {
   
   
            return (Advisor) adviceObject;
        }
        if (!(adviceObject instanceof Advice)) {
   
   
            throw new UnknownAdviceTypeException(adviceObject);
        }
        Advice advice = (Advice) adviceObject;
        if (advice instanceof MethodInterceptor) {
   
   
            // So well-known it doesn't even need an adapter.
            return new DefaultPointcutAdvisor(advice);
        }
        for (AdvisorAdapter adapter : this.adapters) {
   
   
            // Check that it is supported.
            if (adapter.supportsAdvice(advice)) {
   
   
                return new DefaultPointcutAdvisor(advice);
            }
        }
        throw new UnknownAdviceTypeException(advice);
    }

    //获取增强的方法拦截器
    @Override
    public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
   
   
        List<MethodInterceptor> interceptors = new ArrayList<>(3);
        //通知
        Advice advice = advisor.getAdvice();
        if (advice instanceof MethodInterceptor) {
   
   
            interceptors.add((MethodInterceptor) advice);
        }
        for (AdvisorAdapter adapter : this.adapters) {
   
   

            if (adapter.supportsAdvice(advice)) {
   
   
                //通过适配器把advisor转发成MethodInterceptor
                interceptors.add(adapter.getInterceptor(advisor));
            }
        }
        if (interceptors.isEmpty()) {
   
   
            throw new UnknownAdviceTypeException(advisor.getAdvice());
        }
        return interceptors.toArray(new MethodInterceptor[0]);
    }

    //注册适配器
    @Override
    public void registerAdvisorAdapter(AdvisorAdapter adapter) {
   
   
        this.adapters.add(adapter);
    }

}

下面是 MethodBeforeAdviceAdapter的源码:

class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
   
   

    @Override
    public boolean supportsAdvice(Advice advice) {
   
   
        //是否支持
        return (advice instanceof MethodBeforeAdvice);
    }

    @Override
    public MethodInterceptor getInterceptor(Advisor advisor) {
   
   
        MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
        //给定一个MethodBeforeAdvice 前置通知  ,返回一个MethodBeforeAdviceInterceptor 方法前置拦截
        return new MethodBeforeAdviceInterceptor(advice);
    }

}

MethodBeforeAdviceInterceptor 是针对于前置通知的拦截器,在拦截方法的执行之前,可用触发前置通知,源码如下:

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
   
   
    //方法前置通知增强
    private MethodBeforeAdvice advice;


    /**
     * Create a new MethodBeforeAdviceInterceptor for the given advice.
     * @param advice the MethodBeforeAdvice to wrap
     */
    public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
   
   
        Assert.notNull(advice, "Advice must not be null");
        this.advice = advice;
    }

    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
   
   
        //调用前置通知增强
        this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
        //调用目标方法
        return mi.proceed();
    }

}

下面是 AfterReturningAdviceAdapter 后置通知适配器源码:

class AfterReturningAdviceAdapter implements AdvisorAdapter, Serializable {
   
   

    @Override
    public boolean supportsAdvice(Advice advice) {
   
   
        return (advice instanceof AfterReturningAdvice);
    }

    @Override
    public MethodInterceptor getInterceptor(Advisor advisor) {
   
   
        AfterReturningAdvice advice = (AfterReturningAdvice) advisor.getAdvice();
        return new AfterReturningAdviceInterceptor(advice);
    }

}

下面是 AfterReturningAdviceInterceptor后置通知拦截器

public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {
   
   

    private final AfterReturningAdvice advice;


    /**
     * Create a new AfterReturningAdviceInterceptor for the given advice.
     * @param advice the AfterReturningAdvice to wrap
     */
    public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) {
   
   
        Assert.notNull(advice, "Advice must not be null");
        this.advice = advice;
    }

    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
   
   
        //先调用目标方法
        Object retVal = mi.proceed();
        //再调用后置增强
        this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
        return retVal;
    }

}

下面是ThrowsAdviceInterceptor 异常通知拦截器:

public class ThrowsAdviceInterceptor implements MethodInterceptor, AfterAdvice {
   
   

    private static final String AFTER_THROWING = "afterThrowing";

    private static final Log logger = LogFactory.getLog(ThrowsAdviceInterceptor.class);


    private final Object throwsAdvice;
    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
   
   
        try {
   
   
            //执行目标方法
            return mi.proceed();
        }
        catch (Throwable ex) {
   
   
            //收集异常,获取异常增强方法
            Method handlerMethod = getExceptionHandler(ex);
            if (handlerMethod != null) {
   
   
                //调用异常增强
                invokeHandlerMethod(mi, ex, handlerMethod);
            }
            throw ex;
        }
    }

    private void invokeHandlerMethod(MethodInvocation mi, Throwable ex, Method method) throws Throwable {
   
   
        Object[] handlerArgs;
        if (method.getParameterCount() == 1) {
   
   
            handlerArgs = new Object[] {
   
    ex };
        }
        else {
   
   
            handlerArgs = new Object[] {
   
   mi.getMethod(), mi.getArguments(), mi.getThis(), ex};
        }
        try {
   
   
            //调用异常增强
            method.invoke(this.throwsAdvice, handlerArgs);
        }
        catch (InvocationTargetException targetEx) {
   
   
            throw targetEx.getTargetException();
        }
    }

使用反射调用方法

上面分析了Advice通知的注入过程,以及前置,后置,异常通知拦截器代码分析,现在代码回到 JdkDynamicAopProxy #invoke方法中 , 得到方法的拦截器后,如果方法没有拦截器通知链,就直接反射调用方法,否则会创建 ReflectiveMethodInvocation来调用方法

//获取此方法的拦截器通知链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

// Check whether we have any advice. If we don't, we can fallback on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
if (chain.isEmpty()) {
   
   
//如果没有拦截器能应用到该方法,直接反射调用方法
    // 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 = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
   
   
    //创建 ReflectiveMethodInvocation 方法调用
    // We need to create a method invocation...
    invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
    // Proceed to the joinpoint through the interceptor chain.
    //通过拦截器链进入连接点
    retVal = invocation.proceed();
}

AopUtils.invokeJoinpointUsingReflection 源码如下:

@Nullable
public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args)
        throws Throwable {
   
   

    // Use reflection to invoke the method.
    try {
   
   
        //反射调用方法
        ReflectionUtils.makeAccessible(method);
        return method.invoke(target, args);
    }
    catch (InvocationTargetException ex) {
   
   
        // Invoked method threw a checked exception.
        // We must rethrow it. The client won't see the interceptor.
        throw ex.getTargetException();
    }
    catch (IllegalArgumentException ex) {
   
   
        throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +
                method + "] on target [" + target + "]", ex);
    }
    catch (IllegalAccessException ex) {
   
   
        throw new AopInvocationException("Could not access method [" + method + "]", ex);
    }
}

通过 ReflectiveMethodInvocation 调用方法

@Override
@Nullable
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;
        if (dm.methodMatcher.matches(this.method, this.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);
    }
}

总结

到这里AOP的源码分析就结束了,最后总结一下大致流程

  1. AopNamespaceHandler中注册了一个AOP解析器 AspectJAutoProxyBeanDefinitionParser
  2. AspectJAutoProxyBeanDefinitionParser创建了 代理自动创建器AnnotationAwareAspectJAutoProxyCreator
  3. AnnotationAwareAspectJAutoProxyCreator 负责解析AOP,和创建代理类
  4. AnnotationAwareAspectJAutoProxyCreator解析切面,找到所有的增强方法封装成增强器,并找到适合Bean的增强器
  5. 调用AbstractAutoProxyCreator创建代理,默认使用 JDKDynamicAopProxy JDK动态代理,如果 proxy-target-class=“true” 使用CglibAopProxy创建CGLIB代理。
  6. 对于前置,后置,异常等等通知都有对应的拦截器,当代理类被调用就会先走方法的拦截器进行增强逻辑的处理。

文章接收,喜欢就一键三连吧,你的肯定是我最大的动力。

相关文章
|
10天前
|
消息中间件 存储 缓存
大厂面试高频:Kafka 工作原理 ( 详细图解 )
本文详细解析了 Kafka 的核心架构和实现原理,消息中间件是亿级互联网架构的基石,大厂面试高频,非常重要,建议收藏。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:Kafka 工作原理 ( 详细图解 )
|
7天前
|
XML Java 开发者
Spring Boot开箱即用可插拔实现过程演练与原理剖析
【11月更文挑战第20天】Spring Boot是一个基于Spring框架的项目,其设计目的是简化Spring应用的初始搭建以及开发过程。Spring Boot通过提供约定优于配置的理念,减少了大量的XML配置和手动设置,使得开发者能够更专注于业务逻辑的实现。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,为开发者提供一个全面的理解。
19 0
|
12天前
|
存储 算法 Java
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
本文详解自旋锁的概念、优缺点、使用场景及Java实现。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
|
12天前
|
存储 安全 Java
面试高频:Synchronized 原理,建议收藏备用 !
本文详解Synchronized原理,包括其作用、使用方式、底层实现及锁升级机制。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
面试高频:Synchronized 原理,建议收藏备用 !
|
13天前
|
XML Java 数据安全/隐私保护
Spring Aop该如何使用
本文介绍了AOP(面向切面编程)的基本概念和术语,并通过具体业务场景演示了如何在Spring框架中使用Spring AOP。文章详细解释了切面、连接点、通知、切点等关键术语,并提供了完整的示例代码,帮助读者轻松理解和应用Spring AOP。
Spring Aop该如何使用
|
1月前
|
存储 缓存 Java
Spring高手之路23——AOP触发机制与代理逻辑的执行
本篇文章深入解析了Spring AOP代理的触发机制和执行流程,从源码角度详细讲解了Bean如何被AOP代理,包括代理对象的创建、配置与执行逻辑,帮助读者全面掌握Spring AOP的核心技术。
38 3
Spring高手之路23——AOP触发机制与代理逻辑的执行
|
18天前
|
Java Spring
[Spring]aop的配置与使用
本文介绍了AOP(面向切面编程)的基本概念和核心思想。AOP是Spring框架的核心功能之一,通过动态代理在不修改原代码的情况下注入新功能。文章详细解释了连接点、切入点、通知、切面等关键概念,并列举了前置通知、后置通知、最终通知、异常通知和环绕通知五种通知类型。
29 1
|
14天前
|
安全 Java 测试技术
Java开发必读,谈谈对Spring IOC与AOP的理解
Spring的IOC和AOP机制通过依赖注入和横切关注点的分离,大大提高了代码的模块化和可维护性。IOC使得对象的创建和管理变得灵活可控,降低了对象之间的耦合度;AOP则通过动态代理机制实现了横切关注点的集中管理,减少了重复代码。理解和掌握这两个核心概念,是高效使用Spring框架的关键。希望本文对你深入理解Spring的IOC和AOP有所帮助。
28 0
|
3月前
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。
|
14天前
|
存储 缓存 Java
大厂面试必看!Java基本数据类型和包装类的那些坑
本文介绍了Java中的基本数据类型和包装类,包括整数类型、浮点数类型、字符类型和布尔类型。详细讲解了每种类型的特性和应用场景,并探讨了包装类的引入原因、装箱与拆箱机制以及缓存机制。最后总结了面试中常见的相关考点,帮助读者更好地理解和应对面试中的问题。
39 4
下一篇
无影云桌面