Spring源码解析8——动态AOP自定义标签和创建AOP代理

1、动态AOP自定义标签

  如果声明了自定义的注解,那么就一定会在程序中的某个地方注册了对应的解析器。我们搜索整个代码,尝试找到注册的地方,全局搜索后发现了在AopNamespaceHandler.class 中对应着这样一段函数:

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
        registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
        //在解析xml配置文件时,一旦遇到<aspectj-autoproxy\>标签时就会使用解析器AspectJAutoProxyBeanDefinitionParser.class 进行解析
        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());
    }

}
1.1、AspectJAutoProxyBeanDefinitionParser.class的内部实现

  所有解析器,因为是对BeanDefinitionParser.interface 接口的统一实现,入口都是从parse() 函数开始的, AspectJAutoProxyBeanDefinitionParser.class 的parse() 函数如下:

    public BeanDefinition parse(Element element, ParserContext parserContext) {
        //注册AnnotationAwareAspectJAutoProxyCreator.class
        AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
        //对于注解中子类的处理
        extendBeanDefinition(element, parserContext);
        return null;
    }

  其中AopNamespaceUtils.class::registerAspectJAnnotationAutoProxyCreatorIfNecessary()函数是我们比较关心的,也是关键逻辑的实现。
AopNamespaceUtils.class:

    public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
            ParserContext parserContext, Element sourceElement) {
        //注册或升级AutoProxyCreator定义beanName为org.Springframework.aop.config.internalAutoProxyCreator的BeanDefinition
        BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
                parserContext.getRegistry(), parserContext.extractSource(sourceElement));
        //对于proxy-target-class以及expose-proxy属性的处理
        useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
        //注册组件并通知,便于监听器做进一步处理,其中beanDefinition的className为AnnotationAwareAspectJAutoProxyCreator
        registerComponentIfNecessary(beanDefinition, parserContext);
    }

在registerAspectJAnnotationAutoProxyCreatorIfNecessary 函数中主要完成了3 件事情,基本上每行代码就是一个完整的逻辑。

1.1.1、注册或者升级AnnotationAwareAspectJAutoProxyCreator

  对于AOP 的实现,基本上都是靠AnnotationAwareAspectJAutoProxyCreator 去完成,它可以根据@Point 注解定义的切点来自动代理相匹配的bean, 但是为了配置简便, Spring 使用了自定义配置来帮助我们自动注册AnnotationAwareAspectJAutoProxyCreator ,其注册过程就是在这里实现的。
AopNamespaceUtils.class:

    @Nullable
    private static BeanDefinition registerOrEscalateApcAsRequired(
            Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {

        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        //如果已经存在了自动代理创建器且存在的自动代理创建器与现在的不一致,那么需要根据优先级来判断到底需要使用哪个
        if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
            //AUTO_PROXY_CREATOR_BEAN_NAME=org.springframework.aop.config.internalAutoProxyCreator
            BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
            if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
                int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
                int requiredPriority = findPriorityForClass(cls);
                if (currentPriority < requiredPriority) {
                    //改变bean最重要的就是改变bean所对应的className属性
                    apcDefinition.setBeanClassName(cls.getName());
                }
            }
            //如果已经存在自动代理创建器并且与将要创建的一致,那么无须再次创建
            return null;
        }

        RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
        beanDefinition.setSource(source);
        beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
        beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        //AUTO_PROXY_CREATOR_BEAN_NAME=org.springframework.aop.config.internalAutoProxyCreator
        registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
        return beanDefinition;
    }

以上代码中实现了自动注册AnnotationAwareAspectJAutoProxyCreator.class的功能,同时这里还涉及了一个优先级的问题,如果已经存在了自动代理创建器,而且存在的自动代理创建器与现在的不一致,那么需要根据优先级来判断到底需要使用哪个。

1.1.2、处理proxy-target-class以及expose-proxy属性

  useClassProxyingIfNecessary()函数实现了proxy-target-class 属性以及expose-proxy 属性的处理。
AopNamespaceUtils.class:

    private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) {
        if (sourceElement != null) {
            //对于proxy-target-class属性的处理
            boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
            if (proxyTargetClass) {
                AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
            }
            //对于expose-proxy属性的处理
            boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
            if (exposeProxy) {
                AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
            }
        }
    }

proxy-target-class: Spring AOP 部分使用JDK 动态代理或者CGLIB 来为目标对象创建代理(建议尽量使用JDK 的动态代理)。如果被代理的目标对象实现了至少一个接口,则会使用JDK 动态代理。所有该目标类型实现的接口都将被代理。若该目标对象没有实现任何接口,则创建一个CGLIB 代理。如果你希望强制使用CGLIB 代理(例如希望代理目标对象的所有方法,而不只是实现自接口的方法),那也可以。但是需要考虑以下2个问题。
①、无法通知(advise)Final函数,因为它们不能被覆写。
②、你需要将CGLIB二进制发行包放在classpath下面。
  与之相比,JDK本身就提供了动态代理,强制使用CGLIB代理要将 <aop:config>的proxy-target-class属性设为true:

<aop:config proxy-target-class="true" > ... </aop config>

当需要使用CGLIB 代理和 @AspectJ 自动代理支持,可以按照以下方式设置<aop:aspectj-autoproxy>的proxy-target-class 属性:

<aop:aspectj-autoproxy proxy-target-class="true" />

而实际使用的过程中才会发现细节问题的差别, The devil is in the details 。

  • JDK 动态代理:其代理对象必须是某个接口的实现,它是通过在运行期间创建一个接口的实现类来完成对目标对象的代理。
  • CGLIB 代理:实现原理类似于JDK 动态代理,只是它在运行期间生成的代理对象是针对目标类扩展的子类。CGLIB是高效的代码生成包,底层是依靠ASM (开源的Java字节码编辑类库)操作字节码实现的,性能比JDK 强。
  • expose-proxy :有时候目标对象内部的自我调用将无法实施切面中的增强,如下示例:
    image
      此处的this 指向目标对象,因此调用this.b()将不会执行b事务切面,即不会执行事务增强,因此b()函数的事务定义“@Transactiona l(propagation = Propagation.REQUIRES_NEW)”将不会实施,为了解决这个问题,我们可以这样做:
<aop:aspectj-autoproxy expose-proxy="true" />

  然后将以上代码中的“this.b();”修改为"((AService)AopContext.currentProxy()).b();"即可。通过以上的修改便可以完成对a() 和b() 函数的同时增强。
  最后注册组件并通知,便于监听器做进一步处理,这里就不再一一赘述了。

2、创建AOP代理

  上文中讲解了通过自定义配置完成了对AnnotationAwareAspectJAutoProxyCreator类型的自动注册,那么这个类到底做了什么工作来完成AOP 的操作呢?首先看AnnotationAwareAspectJAutoProxyCreator.class的层次结构,如下图所示:
image
  在类的层级中,我们看到AnnotationAwareAspectJAutoProxyCreator 实现了BeanPostProcessor接口,而实现BeanPostProcessor接口后,当Spring 加载这个Bean 时会在实例化前调用其postProcessAfterInitialization() 函数,而我们对于AOP 逻辑的分析也由此开始。
  在父类AbstractAutoProxyCreator.class::postProcessAfterInitialization()函数中,代码如下:

    @Override
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
        if (bean != null) {
            //根据给定的bean的class和name构建出一个key,格式:beanClassName_beanName
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                //如果它适合被代理,则需要封装指定bean
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }

    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        //如果已经处理过
        if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
            return bean;
        }
        //无须增强
        if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
            return bean;
        }
        //给定的bean类是否代表一个基础设施类,基础设施类不应代理,或者配置了指定bean不需要自动代理
        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }

        // Create proxy if we have advice.
        //如果存在增强函数则创建代理
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        //如果获取到了增强则需要针对增强创建代理
        if (specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
            //创建代理,在2.3中详细讲解
            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;
    }

AnnotationAwareAspectJAutoProxyCreator.class和AbstractAutoProxyCreator.class的UML图,如下所示:
image
  函数中我们已经看到了代理创建的雏形。当然,真正开始之前还需要经过一些判断,比如是否已经处理过或者是否是需要跳过的bean ,而真正创建代理的代码是从getAdvicesAndAdvisorsForBean()函数开始的。创建代理主要包含了2个步骤:
①、获取增强函数或者增强器;
②、根据获取的增强进行代理。
核心逻辑的时序图如下图所示:
image
  虽然看似简单,但是每个步骤中都经历了大量复杂的逻辑。首先来看看获取增强函数的实现逻辑。
AbstractAdvisorAutoProxyCreator.class

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

        List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
        if (advisors.isEmpty()) {
            return DO_NOT_PROXY;
        }
        return advisors.toArray();
    }

    protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
        List<Advisor> candidateAdvisors = findCandidateAdvisors();//获取增强器
        List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);//寻找匹配增强器
        extendAdvisors(eligibleAdvisors);
        if (!eligibleAdvisors.isEmpty()) {
            eligibleAdvisors = sortAdvisors(eligibleAdvisors);
        }
        return eligibleAdvisors;
    }

对于指定bean 的增强函数的获取一定是包含2个步骤的,获取所有的增强以及寻找所有增强中适用于bean 的增强并应用, findCandidateAdvisors()函数与findAdvisorsThatCanApply()函数 便是做了这两件事情。当然,如果无法找到对应的增强器便返回Object[] DO_NOT_PROXY ,其中DO_NOT_PROXY=null 。

2.1、获取增强器

  由于我们分析的是使用注解进行的AOP ,所以对于自findCandidateAdvisors()函数的实现其实是由AnnotationAwareAspectJAutoProxyCreator.class完成的,我们继续跟踪AnnotationAwareAspectJAutoProxyCreator.class::findCandidateAdvisors()函数
AnnotationAwareAspectJAutoProxyCreator.class:

    @Override
    protected List<Advisor> findCandidateAdvisors() {
        // Add all the Spring advisors found according to superclass rules.
        //当使用注解方式配置AOP的时候并不是丢弃了对XML配置的支持
        //在这里调用父类函数加载配置文件中的AOP声明
        List<Advisor> advisors = super.findCandidateAdvisors();
        // Build Advisors for all AspectJ aspects in the bean factory.
        if (this.aspectJAdvisorsBuilder != null) {
            advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
        }
        return advisors;
    }

AnnotationAwareAspectJAutoProxyCreator间接继承了AbstractAdvisorAutoProxyCreator,在实现获取增强的方法中除了保留父类的获取配置文件中定义的增强外,同时添加了获取Bean 的注解增强的功能,那么其实现正是由this.aspectJAdvisorsBuilder.buildAspectJAdvisors()函数来实现的。该函数的实现逻辑如下:
①、获取所有beanName ,这一步骤中所有在beanFacotry 中注册的bean 都会被提取出来。
②、遍历所有beanName , 并找出声明Aspect} 注解的类,进行进一步的处理。
③、对标记为AspectJ 注解的类进行增强器的提取。
④、将提取结果加入缓存。
  现在我们来看看函数实现, 对Spring 中所有的类进行分析, 提取Advisor:
BeanFactoryAspectJAdvisorsBuilder.class

public List<Advisor> buildAspectJAdvisors() {
        List<String> aspectNames = this.aspectBeanNames;

        if (aspectNames == null) {
            synchronized (this) {
                aspectNames = this.aspectBeanNames;
                if (aspectNames == null) {
                    List<Advisor> advisors = new ArrayList<>();
                    aspectNames = new ArrayList<>();
                    //获取所有的beanName
                    String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                            this.beanFactory, Object.class, true, false);
                    //循环所有的beanName找出对应的增强函数
                    for (String beanName : beanNames) {
                        //不合法的bean则略过,由子类定义规则,默认返回true
                        if (!isEligibleBean(beanName)) {
                            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.
                        //获取对应的bean的类型
                        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);
                                //解析标记AspectJ注解中的增强函数
                                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 ArrayList<>();
        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;
    }

  至此,我们已经完成了Advisor 的提取, 在上面的步骤中最为重要也最为繁杂的就是增强器的获取。而这一功能委托给了getAdvisors()函数去实现(this.advisorFactorγ. getAdvisors(factory))。
ReflectiveAspectJAdvisorFactory.class

    @Override
    public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
        //获取标记为AspectJ的class
        Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
        //获取标记为AspectJ的name
        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 ArrayList<>();
        for (Method method : getAdvisorMethods(aspectClass)) {
            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.
        //获取DeclareParents注解
        for (Field field : aspectClass.getDeclaredFields()) {
            Advisor advisor = getDeclareParentsAdvisor(field);
            if (advisor != null) {
                advisors.add(advisor);
            }
        }

        return advisors;
    }
    
    private List<Method> getAdvisorMethods(Class<?> aspectClass) {
        final List<Method> methods = new ArrayList<>();
        ReflectionUtils.doWithMethods(aspectClass, method -> {
            // Exclude pointcuts
            //声明为Pointcut的函数不处理
            if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
                methods.add(method);
            }
        }, ReflectionUtils.USER_DECLARED_METHODS);
        if (methods.size() > 1) {
            methods.sort(METHOD_COMPARATOR);
        }
        return methods;
    }

  函数中首先完成了对增强器的获取,包括获取注解以及根据注解生成增强的步骤,然后考虑到在配置中可能会将增强配置成延迟初始化,那么需要在首位加入同步实例化增强器以保证增强使用之前的实例化,最后是对@DeclareParents 注解的获取,下面将详细介绍一下每个步骤。

2.1.1、普通增强器的获取

  普通增强器的获取逻辑通过getAdvisor()函数实现,实现步骤包括对切点的注解的获取以及根据注解信息生成增强。
ReflectiveAspectJAdvisorFactory.class

    @Override
    @Nullable
    public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
            int declarationOrderInAspect, String aspectName) {

        validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
        //切点信息的获取
        AspectJExpressionPointcut expressionPointcut = getPointcut(
                candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
        if (expressionPointcut == null) {
            return null;
        }
        //根据切点信息生成增强器
        return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
                this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
    }

①、切点信息的获取。所谓获取切点信息就是指定注解的表达式信息的获取,如@Before("test()") 。
ReflectiveAspectJAdvisorFactory.class

    @Nullable
    private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
        //获取函数上的注解
        AspectJAnnotation<?> aspectJAnnotation =
                AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
        if (aspectJAnnotation == null) {
            return null;
        }
        //使用AspectJExpressionPointcut实例封装获取的信息
        AspectJExpressionPointcut ajexp =
                new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
        //提取得到的注解中的表达式,如:@Pointcut("execution(* *.*test*(..))")中的execution(* *.*test*(..))
        ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
        if (this.beanFactory != null) {
            ajexp.setBeanFactory(this.beanFactory);
        }
        return ajexp;
    }
    

AbstractAspectJAdvisorFactory.java

    //设置敏感的注解类
    private static final Class<?>[] ASPECTJ_ANNOTATION_CLASSES = new Class<?>[] {
            Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class};
            
    @Nullable
    protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
        for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
            AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
            if (foundAnnotation != null) {
                return foundAnnotation;
            }
        }
        return null;
    }

    @Nullable
    //获取指定函数上的注解并使用AspectJAnnotation封装
    private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) {
        A result = AnnotationUtils.findAnnotation(method, toLookFor);
        if (result != null) {
            return new AspectJAnnotation<>(result);
        }
        else {
            return null;
        }
    }

②、根据切点信息生成增强。所有的增强都由Advisor的实现类InstantiationModelAwarePointcutAdvisorImpl.class在构造函数中统一封装
InstantiationModelAwarePointcutAdvisorImpl.class:

    public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
            Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
            MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
        //test()
        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);
        }
    }

InstantiationModelAwarePointcutAdvisorImpl.class的UML图,如下所示:
image
在封装过程中只是简单地将信息封装在类的实例中,所有的信息单纯地赋值,在实例初始化的过程中还完成了对于增强器的初始化。因为不同的增强所体现的逻辑是不同的,比如@Before("test()")与@After("test()")标签的不同就是增强器增强的位置不同,所以就需要不同的增强器来完成不同的逻辑,而根据注解中的信息初始化对应的增强器就是在instantiateAdvice()函数中实现的。
InstantiationModelAwarePointcutAdvisorImpl.class:

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

ReflectiveAspectJAdvisorFactory.class:

    @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
        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;
        //根据不同的注解类型封装不同的增强器
        switch (aspectJAnnotation.getAnnotationType()) {
            case AtPointcut:
                if (logger.isDebugEnabled()) {
                    logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
                }
                return null;
            case AtAround:
                springAdvice = new AspectJAroundAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                break;
            case AtBefore:
                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;
            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;
    }

从函数中可以看到,Spring 会根据不同的注解生成不同的增强器,例如AtBefore 会对应AspectJMethodBeforeAdvice ,然后在AspectJMethodBeforeAdvice 中完成了增强方法的逻辑。我们尝试分析2个常用的增强器MethodBeforeAdviceInterceptor和AspectJAfterAdvice的实现。MethodBeforeAdviceInterceptor和AspectJAfterAdvice的UML图,如下所示:
image

  • MethodBeforeAdviceInterceptor
    我们首先查看MethodBeforeAdviceInterceptor.class的内部实现
@SuppressWarnings("serial")
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
    //代表着前置增强的AspectJMethodBeforeAdvice
    private final 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();
    }
}

AspectJMethodBeforeAdvice.class::before()函数

    @Override
    public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {
        invokeAdviceMethod(getJoinPointMatch(), null, null);
    }

AbstractAspectJAdvice.class::invokeAdviceMethod()函数
AbstractAspectJAdvice.class::invokeAdviceMethodWithGivenArgs()函数

    protected Object invokeAdviceMethod(
            @Nullable JoinPointMatch jpMatch, @Nullable Object returnValue, @Nullable Throwable ex)
            throws Throwable {

        return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex));
    }
    
    protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
        Object[] actualArgs = args;
        if (this.aspectJAdviceMethod.getParameterCount() == 0) {
            actualArgs = null;
        }
        try {
            ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
            // TODO AopUtils.invokeJoinpointUsingReflection
            //激活增强函数
            return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
        }
        catch (IllegalArgumentException ex) {
            throw new AopInvocationException("Mismatch on arguments to advice method [" +
                    this.aspectJAdviceMethod + "]; pointcut expression [" +
                    this.pointcut.getPointcutExpression() + "]", ex);
        }
        catch (InvocationTargetException ex) {
            throw ex.getTargetException();
        }
    }

invokeAdviceMethodWithGivenArgs() 函数中的aspectJAdviceMethod()函数正是对于前置增强的函数,在这里实现了调用。

  • AspectJAfterAdvice
    后置增强与前置增强有稍许不一致的地方。回顾之前讲过的前置增强,大致的结构是在拦截器链中放置MethodBeforeAdviceInterceptor,而在MethodBeforeAdviceInterceptor 中又放置了AspectJMethodBeforeAdvice,并在调用invoke()函数时首先串联调用。但是在后置增强的时候却不一
    样,没有提供中间的类,而是直接在拦截器链中使用了中间的AspectJAfterAdvice 。
@SuppressWarnings("serial")
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;
    }
}
2.1.2、增强同步实例化增强器

  如果寻找的增强器不为空而且又配置了增强延迟初始化,那么就需要在首位加入同步实例化增强器。同步实例化增强器ReflectiveAspectJAdvisorFactory.class::SyntheticInstantiationAdvisor.class如下:

@SuppressWarnings("serial")
public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {
    @SuppressWarnings("serial")
    protected static class SyntheticInstantiationAdvisor extends DefaultPointcutAdvisor {
        public SyntheticInstantiationAdvisor(final MetadataAwareAspectInstanceFactory aif) {
            super(aif.getAspectMetadata().getPerClausePointcut(), new MethodBeforeAdvice() {
                //目标方法前调用,类似@Before
                @Override
                public void before(Method method, Object[] args, Object target) throws Throwable {
                    //简单初始化aspect
                    aif.getAspectInstance();
                }
            });
        }
    }
}
2.1.3、获取DeclareParents注解

  DeclareParents主要用于引介增强的注解形式的实现,而其实现方式与普通增强很类似,只不过使用DeclareParentsAdvisor 对功能进行封装。
ReflectiveAspectJAdvisorFactory.class::getDeclareParentsAdvisor()

    @Nullable
    private Advisor getDeclareParentsAdvisor(Field introductionField) {
        DeclareParents declareParents = introductionField.getAnnotation(DeclareParents.class);
        if (declareParents == null) {
            // Not an introduction field
            return null;
        }

        if (DeclareParents.class == declareParents.defaultImpl()) {
            throw new IllegalStateException("'defaultImpl' attribute must be set on DeclareParents");
        }

        return new DeclareParentsAdvisor(
                introductionField.getType(), declareParents.value(), declareParents.defaultImpl());
    }
2.2、寻找匹配的增强器

  前面的函数中已经完成了所有增强器的解析,但是对于所有增强器来讲,并不一定都适用于当前的Bean,还要挑取出适合的增强器,也就是满足我们配置的通配符的增强器。具体实现在findAdvisorsThatCanApply()函数中。
AbstractAdvisorAutoProxyCreator.class::findAdvisorsThatCanApply()

    protected List<Advisor> findAdvisorsThatCanApply(
            List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

        ProxyCreationContext.setCurrentProxiedBeanName(beanName);
        try {
            //过滤已经得到的advisors
            return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
        }
        finally {
            ProxyCreationContext.setCurrentProxiedBeanName(null);
        }
    }

继续看AopUtils.class::findAdvisorsThatCanApply()函数

    public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
        if (candidateAdvisors.isEmpty()) {
            return candidateAdvisors;
        }
        List<Advisor> eligibleAdvisors = new ArrayList<>();
        //首先处理引介增强
        for (Advisor candidate : candidateAdvisors) {
            if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
                eligibleAdvisors.add(candidate);
            }
        }
        boolean hasIntroductions = !eligibleAdvisors.isEmpty();
        for (Advisor candidate : candidateAdvisors) {
            //引介增强已经处理
            if (candidate instanceof IntroductionAdvisor) {
                // already processed
                continue;
            }
            //对于普通bean的处理
            if (canApply(candidate, clazz, hasIntroductions)) {
                eligibleAdvisors.add(candidate);
            }
        }
        return eligibleAdvisors;
    }

  findAdvisorsThatCanApply()函数的主要功能是寻找所有增强器中适用于当前class 的增强器。引介增强与普通的增强处理是不一样的, 所以分开处理。而对于真正的匹配在canApply()函数中实现。
AopUtils.class::canApply()函数

    public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
        if (advisor instanceof IntroductionAdvisor) {
            return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
        }
        else if (advisor instanceof PointcutAdvisor) {
            PointcutAdvisor pca = (PointcutAdvisor) advisor;
            return canApply(pca.getPointcut(), targetClass, hasIntroductions);
        }
        else {
            // It doesn't have a pointcut so we assume it applies.
            return true;
        }
    }

    public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
        Assert.notNull(pc, "Pointcut must not be null");
        if (!pc.getClassFilter().matches(targetClass)) {
            return false;
        }

        MethodMatcher methodMatcher = pc.getMethodMatcher();
        if (methodMatcher == MethodMatcher.TRUE) {
            // No need to iterate the methods if we're matching any method anyway...
            return true;
        }

        IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
        if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
            introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
        }

        Set<Class<?>> classes = new LinkedHashSet<>();
        if (!Proxy.isProxyClass(targetClass)) {
            classes.add(ClassUtils.getUserClass(targetClass));
        }
        classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

        for (Class<?> clazz : classes) {
            Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
            for (Method method : methods) {
                if (introductionAwareMethodMatcher != null ?
                        introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
                        methodMatcher.matches(method, targetClass)) {
                    return true;
                }
            }
        }

        return false;
    }
2.3、创建代理

  在获取了所有对应bean 的增强器后,便可以进行代理的创建了。
AbstractAutoProxyCreator.class::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);
        //决定对于给定的bean是否应该使用targetClass而不是它的接口代理,
        //检查proxyTargetClass设置以及preserveTargetClass属性
        if (!proxyFactory.isProxyTargetClass()) {
            if (shouldProxyTargetClass(beanClass, beanName)) {
                proxyFactory.setProxyTargetClass(true);
            }
            else {
                evaluateProxyInterfaces(beanClass, proxyFactory);
            }
        }

        Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
        //加入增强器
        proxyFactory.addAdvisors(advisors);
        //设置要代理的class
        proxyFactory.setTargetSource(targetSource);
        //定制代理
        customizeProxyFactory(proxyFactory);
        //用来控制代理工厂被配置后,是否还允许修改通知
        //缺省值为false(即在代理被配置之后,不允许修改代理的配置)
        proxyFactory.setFrozen(this.freezeProxy);
        if (advisorsPreFiltered()) {
            proxyFactory.setPreFiltered(true);
        }

        return proxyFactory.getProxy(getProxyClassLoader());
    }

ProxyProcessorSupport.class::evaluateProxyInterfaces()

    protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
        Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
        boolean hasReasonableProxyInterface = false;
        for (Class<?> ifc : targetInterfaces) {
            if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
                    ifc.getMethods().length > 0) {
                hasReasonableProxyInterface = true;
                break;
            }
        }
        if (hasReasonableProxyInterface) {
            // Must allow for introductions; can't just set interfaces to the target's interfaces only.
            for (Class<?> ifc : targetInterfaces) {
                //添加代理接口
                proxyFactory.addInterface(ifc);
            }
        }
        else {
            proxyFactory.setProxyTargetClass(true);
        }
    }

AbstractAutoProxyCreator.class和ProxyProcessorSupport.class的UML图:
image
  对于代理类的创建及处理,Spring委托给了ProxyFactorγ 去处理,而在此函数中主要是对ProxyFactory 的初始化操作,进而对真正的创建代理做准备,这些初始化操作包括如下内容。
①、获取当前类中的属性。
②、添加代理接口。
③、封装Advisor 并加入到ProxyFactory 中。
④、设置要代理的类。
⑤、当然在Spring 中还为子类提供了定制的函数customizeProxyFactory ,子类可以在此函数中进行对ProxyFactory 的进一步封装。
⑥、进行获取代理操作。
  其中,封装Advisor 并加入到ProxyFactory 中以及创建代理是两个相对繁琐的过程,可以通过ProxyFactory 提供的addAdvisor()函数直接将增强器置入代理创建工厂中,但是将拦截器封装为增强器还是需要一定的逻辑的。
AbstractAutoProxyCreator.class::buildAdvisors()函数

    protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
        // Handle prototypes correctly...
        //解析注册的所有interceptorName
        Advisor[] commonInterceptors = resolveInterceptorNames();

        List<Object> allInterceptors = new ArrayList<>();
        if (specificInterceptors != null) {
            //加入拦截器
            allInterceptors.addAll(Arrays.asList(specificInterceptors));
            if (commonInterceptors.length > 0) {
                if (this.applyCommonInterceptorsFirst) {
                    allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
                }
                else {
                    allInterceptors.addAll(Arrays.asList(commonInterceptors));
                }
            }
        }
        if (logger.isDebugEnabled()) {
            int nrOfCommonInterceptors = commonInterceptors.length;
            int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
            logger.debug("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
                    " common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
        }

        Advisor[] advisors = new Advisor[allInterceptors.size()];
        for (int i = 0; i < allInterceptors.size(); i++) {
            //拦截器进行封装转化为Advisor
            advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
        }
        return advisors;
    }

DefaultAdvisorAdapterRegistry.class::wrap()函数

    @Override
    public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
        //如果要封装的对象本身就是Advisor类型的,那么无须再做过多处理
        if (adviceObject instanceof Advisor) {
            return (Advisor) adviceObject;
        }
        //因为此封装函数只对Advisor与Advice两种类型的数据有效,如果不是将不能封装
        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.
            //如果是MethodInterceptor类型则使用DefaultPointcutAdvisor封装
            return new DefaultPointcutAdvisor(advice);
        }
        //如果存在Advisor 的适配器那么也同样需要进行封装
        for (AdvisorAdapter adapter : this.adapters) {
            // Check that it is supported.
            if (adapter.supportsAdvice(advice)) {
                return new DefaultPointcutAdvisor(advice);
            }
        }
        throw new UnknownAdviceTypeException(advice);
    }

  由于Spring 中涉及过多的拦截器、增强器、增强方法等方式来对逻辑进行增强,所以非常有必要统一封装成Advisor 来进行代理的创建,完成了增强的封装过程,那么解析最重要的一步就是代理的创建与获取了。
ProxyFactory.class::getProxy()

    public Object getProxy(@Nullable ClassLoader classLoader) {
        return createAopProxy().getProxy(classLoader);
    }
2.3.1、创建代理

ProxyCreatorSupport.class::createAopProxy()

    protected final synchronized AopProxy createAopProxy() {
        if (!this.active) {
            activate();
        }
        //创建代理
        return getAopProxyFactory().createAopProxy(this);
    }

DefaultAopProxyFactory.class::createAopProxy()

    @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.");
            }
            if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
                return new JdkDynamicAopProxy(config);
            }
            return new ObjenesisCglibAopProxy(config);
        }
        else {
            return new JdkDynamicAopProxy(config);
        }
    }

到此已经完成了代理的创建,不管我们之前是否阅读过Spring 的源代码,但是都或多或少地听过对于Spring 的代理中JDKProxy 的实现和CglibProxy 的实现。Spring 是如何选取的呢?网上的介绍有很多,现在我们就从源代码的角度分析,看看到底Spring 是如何选择代理方式的。
  从if中的判断条件可以看到3个方面影响着Spring 的判断。

  • optimize:用来控制通过CGLIB 创建的代理是否使用激进的优化策略。除非完全了解AOP 代理如何处理优化,否则不推荐用户使用这个设置。目前这个属性仅用于CGLIB代理,对于JDK 动态代理(默认代理)无效。
  • proxyTargetClass:这个属性为true 时, 目标类本身被代理而不是目标类的接口。如果这个属性值被设为true,CGLIB代理将被创建,设置方式为<aop:aspectj-autoproxy-proxy-target-class="true"> 。
  • hasNoUserSuppliedProxyInterfaces :是否存在代理接口。
    下面是对JDK与Cglib方式的总结。
  • 如果目标对象实现了接口,默认情况下会采用JDK 的动态代理实现AOP 。
  • 如果目标对象实现了接口,可以强制使用CGLIB 实现AOP 。
  • 如果目标对象没有实现接口,必须采用CGLIB 库, Spring 会自动在JDK 动态代理和CGLIB 之间转换。
    如何强制使用CGLIB实现AOP?
  • 添加CGLIB 库, Spring_HOME/cglib/* .jar。
  • 在Spring 配直文件中加入<aop:aspectj-autoproxy proxy-target-class="true">。
    JDK动态代理和CGLIB 字节码生成的区别?
  • JDK 动态代理只能对实现了接口的class生成代理,而不能针对未实现接口的class。
  • CGLIB 是针对class实现代理,主要是对指定的class生成一个子class,覆盖其中的方法,因为是继承,所以该类或方法最好不要声明成final 。
2.3.2、获取代理

  确定了使用哪种代理方式后便可以进行代理的创建了,但是创建之前有必要回顾一下两种方式的使用方法。

我们再次来回顾一下使用JDK 代理的方式,在整个创建过程中,对于InvocationHandler的创建是最为核心的,在自定义的InvocationHandler 中需要重写3 个函数。
①、构造函数,将代理的对象传入。
②、invoke() 函数,此函数中实现了AOP 增强的所有逻辑。
③、getProxy() 函数,此函数千篇一律,但是必不可少。

那么,我们看看Spring 中的JDK 代理实现是不是也是这么做的呢?继续之前的跟踪,到达JdkDynamicAopProxy.class 的getProxy():
JdkDynamicAopProxy.class::getProxy()

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

通过之前的示例我们知道, JDKProxy 的使用关键是创建自定义的InvocationHandler ,而InvocationHandler 中包含了需要覆盖的函数getProxy() ,而当前的方法正是完成了这个操作。再次确认一下JdkDynamicAopProxy 也确实实现了lnvocationHandler 接口,那么我们就可以推断出,在JdkDynamicAopProxy 中一定会有个invoke() 函数,并且JdkDynamicAopProxy 会把AOP的核心逻辑写在其中。查看代码,果然有这样一个函数:
JdkDynamicAopProxy.class::invoke()

    @Override
    @Nullable
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object oldProxy = null;
        boolean setProxyContext = false;

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

        try {
            //equals()函数的处理
            if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
                // The target does not implement the equals(Object) method itself.
                return equals(args[0]);
            }
            //hash()函数的处理
            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);
            }
            /*
             * Class 类的isAssignableFrom(Class cls )方法:
             * 如果调用这个方法的class 或接口与参数cls 表示的类或接口相间,
             * 或者是参数cls 表示的类或接口的父类,则返回true 。
             * 形象地:自身类.class.isAssignableFrom (自身类或子类.class) 返回true
             * 例:
             *System.out.println(ArrayList.class.isAssignableFrom(Object.class));
             * //false
             * System.out.println(Object.class.isAssignableFrom(ArrayList.class));
             * //true
             * */
            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 {
                // We need to create a method invocation...
                //将拦截器封装在ReflectiveMethodInvocation
                //以便于使用其proceed()函数进行链接表用拦截器
                MethodInvocation 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);
            }
        }
    }

上面的函数中最主要的工作就是创建了一个拦截器链,并使用ReflectiveMethodlnvocation.class进行了链的封装,而在ReflectiveMethodlnvocation.class的proceed()函数中实现了拦截器的逐一调用,那么我们继续来探究,在proceed()函数中是怎么实现前置增强在目标方法前调用后置增强在目标方法后调用的逻辑呢?
ReflectiveMethodInvocation.class::proceed()

    @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.
            /*
            * 普通拦截器,直接调用拦截器,比如:
            * ExposeInvocationInterceptor、
            * DelegatePerTargetObjectIntroductionInterceptor、
            * MethodBeforeAdviceInterceptor、
            * AspectJAroundAdvice、
            * AspectJAfterAdvice
            * */
            //将this作为参数传递以保证当前实例中调用链的执行
            return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
        }
    }

在proceed()函数中,或许代码逻辑并没有我们想象得那么复杂, ReflectiveMethodInvocation.class中的主要职责是维护了链接调用的计数器,记录着当前调用链接的位置,以便链可以有序地进行下去,那么在这个方法中并没有我们之前设想的维护各种增强的顺序,而是将此工作委托给了各个增强器,使各个增强器在内部进行逻辑实现。

  • CGLIB使用示例:
      CGLIB 是一个强大的高性能的代码生成包。它广泛地被许多AOP 的框架使用,例如Spring AOP 和dynaop ,为它们提供方法Interception (拦截)。最流行的ORMapping 工具Hibernate也使用CGLIB 来代理单端single-ended (多对一和一对一)关联(对集合的延迟抓取是采用其它机制实现的)。EasyMock 和jMock 是通过使用模仿( moke )对象来测试Java 代码的包。它们都通过使用CGLIB 来为那些没有接口的类创建模仿( moke )对象。
      CGLIB 包的底层通过使用一个小而快的字节码处理框架ASM ,来转换字节码并生成新的类。除了CGLIB 包,脚本语言例如Groovy 和BeanShell ,也是使用ASM 来生成Java 的字节码。当然不鼓励直接使用ASM , 因为它要求你必须对JVM 内部结构(包括class 文件的格式和指令集) 都很熟悉。
      我们先快速地了解CGLIB 的使用示例。
    image
    运行结果如下:
    image
    可以看到System.out.println(demo), demo 首先调用了toString()函数,然后又调用了hashCode,生成的对象为EnhancerDemo$$EnhancerByCGLIB$$bc9b2066 的实例,这个类是运行时由CGLIB 产生的。
      完成CGLIB 代理的类是委托给CglibAopProxy 类去实现的,我们进入这个类一探究竟。
      按照前面提供的示例,我们容易判断出来, CglibAopProxy 的入口应该是在getProxy()函数,也就是说在CglibAopProxy 类的getProxy()函数中实现了Enhancer 的创建及接口封装。
    CglibAopProxy.class::getProxy()
    @Override
    public Object getProxy(@Nullable ClassLoader classLoader) {
        if (logger.isDebugEnabled()) {
            logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
        }

        try {
            Class<?> rootClass = this.advised.getTargetClass();
            Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

            Class<?> proxySuperClass = rootClass;
            if (ClassUtils.isCglibProxyClass(rootClass)) {
                proxySuperClass = rootClass.getSuperclass();
                Class<?>[] additionalInterfaces = rootClass.getInterfaces();
                for (Class<?> additionalInterface : additionalInterfaces) {
                    this.advised.addInterface(additionalInterface);
                }
            }

            // Validate the class, writing log messages as necessary.
            //验证Class
            validateClassIfNecessary(proxySuperClass, classLoader);

            // Configure CGLIB Enhancer...
            //创建及配置Enhancer
            Enhancer enhancer = createEnhancer();
            if (classLoader != null) {
                enhancer.setClassLoader(classLoader);
                if (classLoader instanceof SmartClassLoader &&
                        ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
                    enhancer.setUseCache(false);
                }
            }
            enhancer.setSuperclass(proxySuperClass);
            enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
            enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
            enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
            //设置拦截器
            Callback[] callbacks = getCallbacks(rootClass);
            Class<?>[] types = new Class<?>[callbacks.length];
            for (int x = 0; x < types.length; x++) {
                types[x] = callbacks[x].getClass();
            }
            // fixedInterceptorMap only populated at this point, after getCallbacks call above
            enhancer.setCallbackFilter(new ProxyCallbackFilter(
                    this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
            enhancer.setCallbackTypes(types);

            // Generate the proxy class and create a proxy instance.
            //生成代理类以及创建代理
            return createProxyClassAndInstance(enhancer, callbacks);
        }
        catch (CodeGenerationException | IllegalArgumentException ex) {
            throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
                    ": Common causes of this problem include using a final class or a non-visible class",
                    ex);
        }
        catch (Throwable ex) {
            // TargetSource.getTarget() failed
            throw new AopConfigException("Unexpected AOP exception", ex);
        }
    }

以上函数完整地阐述了一个创建Spring 中的Enhancer 的过程,读者可以参考Enhancer 的文档查看每个步骤的含义,这里最重要的是通过getCallbacks ()函数设置拦截器链。

    private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
        // Parameters used for optimization choices...
        //对于expose-proxy 属性的处理
        boolean exposeProxy = this.advised.isExposeProxy();
        boolean isFrozen = this.advised.isFrozen();
        boolean isStatic = this.advised.getTargetSource().isStatic();

        // Choose an "aop" interceptor (used for AOP calls).
        //将拦截器封装在DynamicAdvisedInterceptor 中
        Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

        // Choose a "straight to target" interceptor. (used for calls that are
        // unadvised but can return this). May be required to expose the proxy.
        Callback targetInterceptor;
        if (exposeProxy) {
            targetInterceptor = (isStatic ?
                    new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
                    new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
        }
        else {
            targetInterceptor = (isStatic ?
                    new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
                    new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
        }

        // Choose a "direct to target" dispatcher (used for
        // unadvised calls to static targets that cannot return this).
        Callback targetDispatcher = (isStatic ?
                new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());
        
        Callback[] mainCallbacks = new Callback[] {
                //将拦截器链加入Callback 中
                aopInterceptor,  // for normal advice
                targetInterceptor,  // invoke target without considering advice, if optimized
                new SerializableNoOp(),  // no override for methods mapped to this
                targetDispatcher, this.advisedDispatcher,
                new EqualsInterceptor(this.advised),
                new HashCodeInterceptor(this.advised)
        };

        Callback[] callbacks;

        // If the target is a static one and the advice chain is frozen,
        // then we can make some optimizations by sending the AOP calls
        // direct to the target using the fixed chain for that method.
        if (isStatic && isFrozen) {
            Method[] methods = rootClass.getMethods();
            Callback[] fixedCallbacks = new Callback[methods.length];
            this.fixedInterceptorMap = new HashMap<>(methods.length);

            // TODO: small memory optimization here (can skip creation for methods with no advice)
            for (int x = 0; x < methods.length; x++) {
                Method method = methods[x];
                List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
                fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
                        chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
                this.fixedInterceptorMap.put(methods.toString(), x);
            }

            // Now copy both the callbacks from mainCallbacks
            // and fixedCallbacks into the callbacks array.
            callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
            System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
            System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
            this.fixedInterceptorOffset = mainCallbacks.length;
        }
        else {
            callbacks = mainCallbacks;
        }
        return callbacks;
    }

在getCallback()函数中Spring 考虑了很多情况,但是对于我们来说,只需要理解最常用的就可以了,比如将advised 属性封装在DynamicAdvisedInterceptor 并加入在callbacks 中,这么做的目的是什么呢,如何调用呢?在前面的示例中,我们了解到CGLIB 中对于方法的拦截是通过将自定义的拦截器(实现MethodInterceptor 接口)加入Callback 中并在调用代理时直接激活拦截器中的intercept() 函数来实现的,那么在getCallback() 中正是实现了这样一个目的, DynamicAdvisedInterceptor继承自MethodInterceptor ,加入Callback 中后,在再次调用代理时会直接调用DynamicAdvisedlnterceptor 中的intercept() 函数,由此推断,对于CGLIB 方式实现的代理,其核心逻辑必然在DynamicAdvisedInterceptor.class 中的intercept()函数中。
CglibAopProxy.class::DynamicAdvisedInterceptor.class::intercept()函数

        @Override
        @Nullable
        public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            Object oldProxy = null;
            boolean setProxyContext = false;
            Object target = null;
            TargetSource targetSource = this.advised.getTargetSource();
            try {
                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);
                //获取拦截器链
                List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
                Object retVal;
                // Check whether we only have one InvokerInterceptor: that is,
                // no real advice, but just reflective invocation of the target.
                if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
                    // 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 = methodProxy.invoke(target, argsToUse);
                }
                else {
                    // We need to create a method invocation...
                    //进入链
                    retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
                }
                retVal = processReturnType(proxy, target, method, retVal);
                return retVal;
            }
            finally {
                if (target != null && !targetSource.isStatic()) {
                    targetSource.releaseTarget(target);
                }
                if (setProxyContext) {
                    // Restore old proxy.
                    AopContext.setCurrentProxy(oldProxy);
                }
            }
        }

上述的实现与JDK 方式实现代理中的invoke()函数大同小异,都是首先构造链,然后封装此链进行串联调用,稍有些区别就是在JDK 中直接构造Refl ectiveMethodlnvocation ,而在cglib中使用CglibMethodlnvocation 。CglibMethodlnvocation 继承自Refl ectiveMethodlnvocation,但是proceed()函数没有重写。

posted @ 2025-12-28 23:46  Carey_ccl  阅读(6)  评论(0)    收藏  举报