Spring源码分析(十)AOP源码分析

AOP中的几个概念

Advisor 和 Advice

Advice

我们通常都会把他翻译为通知,其实很不好理解,其实他还有另外一个意思,就是“建议”,我觉得把Advice理解为“建议”会更好。就是代理的逻辑。

比如,我们已经完成了一个功能,这时客户跟我们说,我建议在这个功能之前可以再增加一些逻辑,再之后再增加一些逻辑。

在Spring中,Advice分为:

  1. 前置Advice:MethodBeforeAdvice
  2. 后置Advice:AfterReturningAdvice
  3. 环绕Advice:MethodInterceptor
  4. 异常Advice:ThrowsAdvice

在利用Spring AOP去生成一个代理对象时,我们可以设置这个代理对象的Advice。

而对于Advice来说,它只表示了“建议”,它没有表示这个“建议”可以用在哪些方面。

就好比,我们已经完成了一个功能,客户给这个功能提了一个建议,但是这个建议也许也能用到其他功能上。

这时,就出现了Advisor,表示一个Advice可以应用在哪些地方,而“哪些地方”就是Pointcut(切点)。 

Pointcut

切点,表示我想让哪些地方加上我的代理逻辑。

比如某个方法,

比如某些方法,

比如某些方法名前缀为“find”的方法,

比如某个类下的所有方法,等等。

在Pointcut中,有一个MethodMatcher,表示方法匹配器。

 Advisor

 就等于Pointcut+Advice.

 

 Spring中的AOP代理类是通过一个ProxyFactory类来实现的。

 先简单介绍下这个类的简单用法:

public static void main(String[] args) {

      AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);

      UserInterface userService = (UserInterface) applicationContext.getBean("userService");

      userService.test();

//       testAop();

   }

   public static void testAop(){
      ProxyFactory proxyFactory = new ProxyFactory();
      // 设置目标对象
      proxyFactory.setTarget(new UserService());
//    proxyFactory.setTargetClass(UserService.class);

      proxyFactory.addInterface(UserInterface.class);   // 表示想使用jdk动态代理
      proxyFactory.getTargetSource();
//    生成代理逻辑 ,注意这里添加的只是一个Advice,底层是要封装成一个Advisor来交给代理工厂管理的。
//    这里添加了Advice,底层使用 DefaultPointcutAdvisor 封装,它的PointCut是Pointcut.TRUE  表示匹配所有类的切点的都使用
      proxyFactory.addAdvice(new MethodBeforeAdvice() {
         @Override
         public void before(Method method, Object[] args, Object target) throws Throwable {
            System.out.println(method.getName()+"方法调用之前执行的代理逻辑");
         }
      });
//    UserService 实现了 UserInterface 接口

//    生成代理对象  UserService 是个实现类,如果是cglib动态代理,代理类是可以强转成它的,但是如果是jdk动态代理,它就不能强转成UserService类
//    因为cglib是基于子类来实现的,jdk动态代理是基于接口实现类来的

//        UserService proxy = (UserService) proxyFactory.getProxy();

//    jdk动态代理   {代理类  extends Proxy implement 目标接口}
      UserInterface proxy = (UserInterface) proxyFactory.getProxy();

      proxy.test();
   }

1:上面ProxyFactory的构造方法,会把传进去的目标对象封装成一个TargetSource

public void setTarget(Object target) {
        setTargetSource(new SingletonTargetSource(target));
    }

 2:   还有一种设置目标对象的方式,就是:proxyFactory.setTargetClass(UserService.class);

    public void setTargetClass(@Nullable Class<?> targetClass) {
        this.targetSource = EmptyTargetSource.forClass(targetClass);
    }

两种设置方式得到的  this.targetSource 这个属性是不一样的,

一个是: EmptyTargetSource  ,一个是 SingletonTargetSource,他们都继承了 TargetSource,但是对于SingletonTargetSource来说,它的target属性,和getTargetClass都是可以得到值的。

 

 但是对于EmptyTargetSource  来说,它只有getTargetClass能得到值,因为是直接赋值的,它的getTarget是直接返回null的。

 上面代理工厂ProxyFactory#getProxy得到一个代理类中,会先得到一个具体的代理工厂,有两种jdk的代理工厂和cglib的代理工厂。

public Object getProxy() {
        return createAopProxy().getProxy();
    }

    protected final synchronized AopProxy createAopProxy() {
        if (!this.active) {
            activate();
        }
        // 默认用的就是DefaultAopProxyFactory
        return getAopProxyFactory().createAopProxy(this);
    }

 DefaultAopProxyFactory#createAopProxy 中:

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        // Spring到底何时使用cglib,何时使用jdk动态代理
        // 如果设置的targetClass是一个接口,会使用jdk动态代理
        // 默认情况下(optimize为false, isProxyTargetClass为false), ProxyFactory添加了接口时,也会使用jdk动态代理

        // 这个config 就是外面的按个ProxyFactory 它的父类 extends ProxyConfig implements Advised
//        config.isOptimize() 跟CGlib优化 可以在外面设置 ,默认为false
//        config.isProxyTargetClass()  默认为false ,是否使用cglib,  这个属性也可以通过 @EnableAspectJAutoProxy 注解设置,注解属性里面也有这个属性
//     hasNoUserSuppliedProxyInterfaces 是不是没有用户提供的代理接口 :这个指的是 可以通过proxyFactory.addInterface() 添加接口
//        添加之后 hasNoUserSuppliedProxyInterfaces(config)会判断   是否进入下面的逻辑
        if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
//            这个 getTargetClass() 就是外面setTarget或者 setTargetClass 之后可以得到的值
            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.");
            }
//            如果 targetClass 是接口就使用jdk的动态代理 ,如果外面是通过setTarget赋值的,那么targetClass肯定不是接口,因为参数是个对象
//            setTargetClass  设置的可以是个接口
            if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
//                返回jdk的代理工厂
                return new JdkDynamicAopProxy(config);
            }
//            返回cglib的代理工厂
            return new ObjenesisCglibAopProxy(config);
        }
        else {
            return new JdkDynamicAopProxy(config);
        }
    }

 而一般在我们使用过程中,如果只开启了注解:@EnableAspectJAutoProxy  ,Spring会根据类是否有接口来判断是否用jdk动态代理还是cglib动态代理。如果在  @EnableAspectJAutoProxy(proxyTargetClass = true) 加上属性,则就会都优先使用cglib的动态代理。


上面分析了得到代理工厂,代理工厂得到得到代理类是 getProxy()。代理工厂两个: JdkDynamicAopProxy,ObjenesisCglibAopProxy。

JdkDynamicAopProxy#getProxy()

jdk动态代理生成的代理类是实现一些指定接口的代理类,实现那些接口是: AopProxyUtils.completeProxiedInterfaces(this.advised, true); 查找。

    public Object getProxy(@Nullable ClassLoader classLoader) {

//        this.advised 就是ProxyFactory对象
        if (logger.isTraceEnabled()) {
            logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
        }
        // 获取生成代理对象所需要实现的接口
//        如果通过指定了 proxyFactory.addInterface 指定了接口,则算上一个,如果没有指定则看targetClass 是不是接口  如果是的话这个接口算上一个
//        最后还会加上Spring 自带的三个接口 SpringProxy(只是标记接口,标记是个AOP代理类)、Advised(可以管理AOP 的通知,在使用代理类的时候可以强转为它 进行管理)、
//        DecoratingProxy
        Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);

        // 判断这些接口中有没有定义equals方法,hashcode方法
        findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
        // 针对所指定的接口生成代理对象,包括用户所添加的接口以及SpringProxy、Advised、DecoratingProxy
        // 所以生成的代理对象可以强制转换成任意一个接口类型
        //  用的也是JDK中的代理方式, 传入了this对象,也就是JdkDynamicAopProxy implements AopProxy, InvocationHandler
        //   调用代理类方法的时候,就会走 下面的invoke方法
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }

 Spring中创建AOP代理的方式

 上面创建代理类举例子是通过ProxyFactory来的,在spring中是底层才用到这个类,在spring中有几种实用的创建AOP代理的方式。

1:通过 BeanNameAutoProxyCreator  这个后置处理器,进行自动代理。

看到它继承了 AbstractAutoProxyCreator,父类实现了 SmartInstantiationAwareBeanPostProcessor后置处理器,里面肯定有个postProcessBeforeInstantiation,postProcessAfterInitialization。

在postProcessBeforeInstantiation逻辑中会有判断是否需要提前创建代理对象的逻辑。还会判断是否要跳过当前bean的代理逻辑的处理: this.advisedBeans.put(cacheKey, Boolean.FALSE);

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
        Object cacheKey = getCacheKey(beanClass, beanName);
        if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
            // advisedBeans中存的是当前这个bean需不需要代理
            if (this.advisedBeans.containsKey(cacheKey)) {
                return null;
            }
            // 当前bean是不是不需要进行代理
            if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
                this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return null;
            }
        }
        // 查看是否需要提前生成代理对象
        // Create proxy here if we have a custom TargetSource.
        // Suppresses unnecessary default instantiation of the target bean:
        // The TargetSource will handle target instances in a custom fashion.
        // 判断当前beanClass和beanName是否会生成一个TargetSource,如果生成了,就进行代理
        TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
        if (targetSource != null) {
            if (StringUtils.hasLength(beanName)) {
                this.targetSourcedBeans.add(beanName);
            }
            Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
            // 创建一个代理对象
            Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }
        return null;
    }

一般的AOP代理逻辑处理是在postProcessAfterInitialization中的

    // 正常情况进行AOP的地方
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
        if (bean != null) {
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            // earlyProxyReferences中存的是哪些提前进行了AOP的bean,beanName:AOP之前的对象
            // 注意earlyProxyReferences中并没有存AOP之后的代理对象  BeanPostProcessor
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                // 没有提前进行过AOP,则进行AOP
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        // 为什么不返回代理对象呢?
        return bean;   //
    }

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        // 在当前targetSourcedBeans中存在的bean,表示在实例化之前就产生了代理对象
        if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
            return bean;
        }
        // 当前这个bean不用被代理  this.advisedBean 存储一个bean需不需要被代理
        if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
            return bean;
        }

        // 先判断当前bean是不是要进行AOP,比如当前bean的类型是Pointcut、Advice、Advisor AopInfrastructureBean 那就不需要进行AOP
//        shouldSkip  给子类来实现判断是否需要进行AOP代理
        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }

        // Create proxy if we have advice.
        //  这么说不对: 获取当前beanClass所匹配的advisors(PointCut+Advice) 或者Advice
        // 也是由子类来实现逻辑的  BeanNameAutoProxyCreator
        // 只是返回一个标记 DO_NOT_PROXY、PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS   看是否需要进行AOP代理
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

        // 如果匹配的advisors不等于null,那么则进行代理,并返回代理对象
        if (specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
            // 基于bean对象和Advisor创建代理对象
            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;
    }

1.1:定义 BeanNameAutoProxyCreator

    // 自动代理 BeanPost
    @Bean
    public BeanNameAutoProxyCreator creator(){
        // BeanPostProcessor
        BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();
//        设置要目标bean的beanName,可以配置多个
        beanNameAutoProxyCreator.setBeanNames("userService");  // bean==>AOP
//        设置拦截器名称,其实就是Advisor= PointCut+Advice
        beanNameAutoProxyCreator.setInterceptorNames("myAdvisor");
        return beanNameAutoProxyCreator;
    }

1.2: 定义Advisor

@Component
public class MyAdvisor implements PointcutAdvisor {
    @Override
    public Pointcut getPointcut() {
//        设置切点信息,通过方法的名字匹配切点
        NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut();
//        设置了切点为 方法名是test的方法
        pointcut.addMethodName("test");
        return pointcut;
    }

    @Override
    public Advice getAdvice() {
//        设置Advice  增强的逻辑
        return new MethodBeforeAdvice() {
            @Override
            public void before(Method method, Object[] args, Object target) throws Throwable {
                System.out.println("Myadvisor方法执行前"+target.getClass().getName());
            }
        };
    }

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

 

 上面的方式配置的AOP逻辑实现了。

2:还有一种通过 DefaultAdvisorAutoProxyCreator来进行AOP逻辑查找匹配的方式。

@Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
        return creator;
    }

 DefaultAdvisorAutoProxyCreator 是找Advisor类型的bean,然后进行匹配。就是上面自定义的MyAdvisor。

这个Bean可以替换掉上面的那个BeanNameAutoProxyCreator。但是这种方式也不方便,因为定义Advisor不够灵活,配置比较麻烦。

3:使用注解,这种方式比较常用。@EnableAspectJAutoProxy

这个注解有 proxyTargetClass 属性默认false(如果为true表示要使用cglib的动态代理),exposeProxy 属性默认为false。

Advisor是通过如下方式:

@Component
@Aspect
public class TestAspect  {
    @Before("execution(public void com.luban.service.UserService.test())")

    public void before(){
        System.out.println("注解前置方法执行");
    }
}

在配置类上加了这个注解之后,这个注解会引入一个类:AspectJAutoProxyRegistrar。和上面的方式相比:

 AspectJAutoProxyRegistrar  继承 ImportBeanDefinitionRegistrar ,具有注册beanDefinition的功能。就是  registerBeanDefinitions方法:注册一个AnnotationAwareAspectJAutoProxyCreator 类。

public void registerBeanDefinitions(
            AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

//        注册一个 AnnotationAwareAspectJAutoProxyCreator 的bean
        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

        AnnotationAttributes enableAspectJAutoProxy =
                AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
        if (enableAspectJAutoProxy != null) {
            if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
                AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
            }
            if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
                AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
            }
        }
    }

 AnnotationAwareAspectJAutoProxyCreator 的继承结构如上图,它不仅可以找到Advisor类型的bean,还可以找@Aspect标注的bean。


这种注解方式的执行流程按照上面的继承关系重新整理一下如下:

1:AbstractAutoProxyCreator

     是个bean的后置处理器,在某个bean的创建过程中,会执行它里面的postProcessBeforeInstantiation,postProcessAfterInitialization

      

 AbstractAutoProxyCreator#postProcessBeforeInstantiation

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
        Object cacheKey = getCacheKey(beanClass, beanName);
        if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
            // advisedBeans中存的是当前这个bean需不需要代理
            if (this.advisedBeans.containsKey(cacheKey)) {
                return null;
            }
            // 当前bean是不是不需要进行代理 里面的两个方法都可以被子类实现,作为自己不同场景下的判断
            if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
                this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return null;
            }
        }
        // 查看是否需要提前生成代理对象
        // Create proxy here if we have a custom TargetSource.
        // Suppresses unnecessary default instantiation of the target bean:
        // The TargetSource will handle target instances in a custom fashion.
        // 判断当前beanClass和beanName是否会生成一个TargetSource,如果生成了,就进行代理
        TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
        if (targetSource != null) {
            if (StringUtils.hasLength(beanName)) {
                this.targetSourcedBeans.add(beanName);
            }
            Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
            // 创建一个代理对象
            Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }
        return null;
    }

 上面有两个方法isInfrastructureClass,shouldSkip可以由子类来判断一个bean要不要进行代理。

AnnotationAwareAspectJAutoProxyCreator #isInfrastructureClass

protected boolean isInfrastructureClass(Class<?> beanClass) {
        // Previously we setProxyTargetClass(true) in the constructor, but that has too
        // broad an impact. Instead we now override isInfrastructureClass to avoid proxying
        // aspects. I'm not entirely happy with that as there is no good reason not
        // to advise aspects, except that it causes advice invocation to go through a
        // proxy, and if the aspect implements e.g the Ordered interface it will be
        // proxied by that interface and fail at runtime as the advice method is not
        // defined on the interface. We could potentially relax the restriction about
        // not advising aspects in the future.
//        调用父类的过滤方法,如果父类没有过滤掉,调用自己增加的增加的过滤方法(过滤掉@Aspect注解标注的bean,因为这是作为Advisor集合的bean)
        return (super.isInfrastructureClass(beanClass) ||
                (this.aspectJAdvisorFactory != null && this.aspectJAdvisorFactory.isAspect(beanClass)));
    }

父类中AbstractAutoProxyCreator#isInfrastructureClass

    protected boolean isInfrastructureClass(Class<?> beanClass) {
//        过滤掉一些 和AOP相关的bean
        boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
                Pointcut.class.isAssignableFrom(beanClass) ||
                Advisor.class.isAssignableFrom(beanClass) ||
                AopInfrastructureBean.class.isAssignableFrom(beanClass);
        if (retVal && logger.isTraceEnabled()) {
            logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");
        }
        return retVal;
    }

 AspectJAwareAdvisorAutoProxyCreator#shouldSkip

    protected boolean shouldSkip(Class<?> beanClass, String beanName) {
        // TODO: Consider optimization by caching the list of the aspect names
        // 得到类型为Advisor的bean,以及被@Aspect注解修饰了的类中所定义的@Before等
        List<Advisor> candidateAdvisors = findCandidateAdvisors();

        // 如果当前beanName是AspectJPointcutAdvisor,那么则跳过
        for (Advisor advisor : candidateAdvisors) {
            if (advisor instanceof AspectJPointcutAdvisor &&
                    ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
                return true;
            }
        }
//        调用父类的的shouldSkip 方法
        return super.shouldSkip(beanClass, beanName);
    }

父类中AbstractAutoProxyCreator#shouldSkip

protected boolean shouldSkip(Class<?> beanClass, String beanName) {
        return AutoProxyUtils.isOriginalInstance(beanName, beanClass);
    }
static boolean isOriginalInstance(String beanName, Class<?> beanClass) {
        if (!StringUtils.hasLength(beanName) || beanName.length() !=
                beanClass.getName().length() + AutowireCapableBeanFactory.ORIGINAL_INSTANCE_SUFFIX.length()) {
            return false;
        }
        return (beanName.startsWith(beanClass.getName()) &&
                beanName.endsWith(AutowireCapableBeanFactory.ORIGINAL_INSTANCE_SUFFIX));
    }

在 AspectJAwareAdvisorAutoProxyCreator#shouldSkip中有一个 findCandidateAdvisors 的方法,找到所有候选者Advisor

它由子类重写了,AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors如下

 
    protected List<Advisor> findCandidateAdvisors() {
        // Add all the Spring advisors found according to superclass rules.
        // 先去调用父类的 findCandidateAdvisors 方法
        // Advisor=Pointcut+Advice (切点加建议) ,获得到所有Advisor类型的bean
        List<Advisor> advisors = super.findCandidateAdvisors();

        // Build Advisors for all AspectJ aspects in the bean factory.
        // 找的是通过AspectJ的方式定义的Advisor
        if (this.aspectJAdvisorsBuilder != null) {
            advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
        }
        return advisors;
    }

假如上面实例化之前的那个方法没有进行Aop代理,那么正常AOP代理对象是在postProcessAfterInitialization中产生的。

AbstractAutoProxyCreator#postProcessAfterInitialization

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
        if (bean != null) {
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            // earlyProxyReferences中存的是哪些提前进行了AOP的bean,beanName:AOP之前的对象
            // 注意earlyProxyReferences中并没有存AOP之后的代理对象  BeanPostProcessor
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                // 没有提前进行过AOP,则进行AOP
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        // 为什么不返回代理对象呢?
        return bean;   //
    }

 
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        // 在当前targetSourcedBeans中存在的bean,表示在实例化之前就产生了代理对象
        if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
            return bean;
        }
        // 当前这个bean不用被代理  this.advisedBean 存储一个bean需不需要被代理
        if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
            return bean;
        }
        // 先判断当前bean是不是要进行AOP,比如当前bean的类型是Pointcut、Advice、Advisor AopInfrastructureBean 那就不需要进行AOP
//        shouldSkip  给子类来实现判断是否需要进行AOP代理
        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }

        // Create proxy if we have advice.
        //  这么说不对: 获取当前beanClass所匹配的advisors(PointCut+Advice) 或者Advice
        // 也是由子类来实现逻辑的  BeanNameAutoProxyCreator
        // 只是返回一个标记 DO_NOT_PROXY、PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS   看是否需要进行AOP代理
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

        // 如果匹配的advisors不等于null,那么则进行代理,并返回代理对象
        if (specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
            // 基于bean对象和Advisor创建代理对象
            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;
    }

AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean
    protected Object[] getAdvicesAndAdvisorsForBean(
            Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {

        // 针对当前bean查找合格的Advisor
        List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
        if (advisors.isEmpty()) {
            return DO_NOT_PROXY;
        }
        return advisors.toArray();
    }

// 查找合格的Advisor(和beanClass匹配)
    protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
        // 得到所有的Advisor
        List<Advisor> candidateAdvisors = findCandidateAdvisors();
        // 进行筛选 筛选和beanClass匹配的Advisor
        List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);

        // 提供给子类去额外的添加advisor
        extendAdvisors(eligibleAdvisors);
        if (!eligibleAdvisors.isEmpty()) {
            // 按order进行排序
            eligibleAdvisors = sortAdvisors(eligibleAdvisors);
        }

        // 返回匹配的Advisor
        return eligibleAdvisors;
    }

    protected List<Advisor> findCandidateAdvisors() {
        // Add all the Spring advisors found according to superclass rules.
        // 先去调用父类的 findCandidateAdvisors 方法
        // Advisor=Pointcut+Advice (切点加建议) ,获得到所有Advisor类型的bean
        List<Advisor> advisors = super.findCandidateAdvisors();

        // Build Advisors for all AspectJ aspects in the bean factory.
        // 找的是通过AspectJ的方式定义的Advisor   找到@Aspect注解标注的类
        if (this.aspectJAdvisorsBuilder != null) {
            advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
        }
        return advisors;
    }

进行创建代理的逻辑:createProxy
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 = new ProxyFactory();
        proxyFactory.copyFrom(this);    // 复制配置参数
        // 是否指定了必须用cglib进行代理
        if (!proxyFactory.isProxyTargetClass()) {
            // 如果没有指定,那么则判断是不是应该进行cglib代理(判断BeanDefinition中是否指定了要用cglib)
            if (shouldProxyTargetClass(beanClass, beanName)) {
                proxyFactory.setProxyTargetClass(true);
            }
            else {
                // 是否进行jdk动态代理,如果当前beanClass实现了某个接口,那么则会使用JDK动态代理
                evaluateProxyInterfaces(beanClass, proxyFactory); // 判断beanClass有没有实现接口
            }
        }


        // 将commonInterceptors和specificInterceptors整合再一起
        Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);

        proxyFactory.addAdvisors(advisors);    // 向ProxyFactory中添加advisor
        proxyFactory.setTargetSource(targetSource); // 被代理的对象
        customizeProxyFactory(proxyFactory);

        proxyFactory.setFrozen(this.freezeProxy);    //
        if (advisorsPreFiltered()) {
            proxyFactory.setPreFiltered(true);
        }

        // 生成代理对象
        return proxyFactory.getProxy(getProxyClassLoader());
    }

 首先创建ProxyFactory对象,开头已经介绍过这个类了。

public void copyFrom(ProxyConfig other) {
        Assert.notNull(other, "Other ProxyConfig object must not be null");
        this.proxyTargetClass = other.proxyTargetClass;  // 是否开启cglib
        this.optimize = other.optimize;
        this.exposeProxy = other.exposeProxy; // 是否将生成的代理对象设置到AopContext中去,后面可以通过AopContext.currentProxy()拿到
        this.frozen = other.frozen;
        this.opaque = other.opaque;
    }

从上面可以看出,是否要用cglib进行代理,不止是看目标对象是否实现了某个接口,还和proxyTargetClass属性有关,这个属性在 @EnableAspectJAutoProxy中有设置,注入AnnotationAwareAspectJAutoProxyCreator的时候赋值进去的,然而看上面的逻辑,就算是
没有设置,还会判断当前bean对应的BeanDefinition中是否有设置一个名为:org.springframework.aop.framework.autoproxy.AutoProxyUtils.preserveTargetClass=true的属性,如果有的话也会设置为true。

 getProxy中,会先判断使用JDK代理工厂还是使用cglib的代理工厂

    public Object getProxy(@Nullable ClassLoader classLoader) {
        // 根据不同的情况得到不同的动态代理工厂,cglib或jdk动态代理
        return createAopProxy().getProxy(classLoader);
    }

    protected final synchronized AopProxy createAopProxy() {
        if (!this.active) {
            activate();
        }
        // 默认用的就是DefaultAopProxyFactory
        return getAopProxyFactory().createAopProxy(this);
    }

AopProxy有两种,一种是JdkDynamicAopProxy,一种是CglibAopProxy

JdkDynamicAopProxy#getProxy

    public Object getProxy(@Nullable ClassLoader classLoader) {

//        this.advised 就是ProxyFactory对象
        if (logger.isTraceEnabled()) {
            logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
        }
        // 获取生成代理对象所需要实现的接口
//        如果通过指定了 proxyFactory.addInterface 指定了接口,则算上一个,如果没有指定则看targetClass 是不是接口  如果是的话这个接口算上一个
//        最后还会加上Spring 自带的三个接口 SpringProxy(只是标记接口,标记是个AOP代理类)、Advised(可以管理AOP 的通知,在使用代理类的时候可以强转为它 进行管理)、
//        DecoratingProxy
        Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);

        // 判断这些接口中有没有定义equals方法,hashcode方法
        findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
        // 针对所指定的接口生成代理对象,包括用户所添加的接口以及SpringProxy、Advised、DecoratingProxy
        // 所以生成的代理对象可以强制转换成任意一个接口类型
        //  用的也是JDK中的代理方式, 传入了this对象,也就是JdkDynamicAopProxy implements AopProxy, InvocationHandler
        //   调用代理类方法的时候,就会走 下面的invoke方法
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }
JdkDynamicAopProxy 本身是一个InvocationHandler,所以当调用目标对象的方法时就会执行JdkDynamicAopProxy#invoke方法。
里面主要的逻辑如下:
上面的 this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);,会得到那些在@Aspect中定义的Advice。这些Advice根据@Before,@After等等的不同,分为AspectJAroundAdvice等等。

然后把这个执行链,还有代理对象,目标对象封装成 ReflectiveMethodInvocation,然后执行其proceed方法,这个方法是个递归调用。
public Object proceed() throws Throwable {
        // We start with an index of -1 and increment early.
//        this.currentInterceptorIndex  默认=-1
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
//  最后执行method本身的逻辑
            return invokeJoinpoint();
        }

        Object interceptorOrInterceptionAdvice =
                this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
        if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
            // Evaluate dynamic method matcher here: static part will already have
            // been evaluated and found to match.
            InterceptorAndDynamicMethodMatcher dm =
                    (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
            Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
            if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
                return dm.interceptor.invoke(this);
            }
            else {
                // Dynamic matching failed.
                // Skip this interceptor and invoke the next in the chain.
                return proceed();
            }
        }
        else {
            // It's an interceptor, so we just invoke it: The pointcut will have
            // been evaluated statically before this object was constructed.
//            调用 AspectJAroundAdvice,AspectJAfterReturningAdvice 等
            return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
        }
    }

以MethodBeforeAdviceInterceptor#invoke为例子
    public Object invoke(MethodInvocation mi) throws Throwable {
      //  先执行@Aspect中@Before标注的方法
        this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
//   然后继续调用下一个Advice方法
        return mi.proceed();  // methodinter target.test();
    }
在 ReflectiveAspectJAdvisorFactory#getAdvisor 中把上面@Aspect的类中的方法封装成Advisor对象。
    public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
            int declarationOrderInAspect, String aspectName) {

        validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
        // 得到当前candidateAdviceMethod方法上的所定义的expression表达式,也就是切点
        AspectJExpressionPointcut expressionPointcut = getPointcut(
                candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
        if (expressionPointcut == null) {
            return null;
        }
        // 构造一个Advisor,封装了切点表达式和当前方法
        return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
                this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
    }

 不同的Advice对应的不同的类,就是上面说的MethodInterceptor.

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

姑苏冷

您的打赏是对原创文章最大的鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值