1. 程式人生 > >Spring基於註解形式的 AOP的原理流程及原始碼解析(一)

Spring基於註解形式的 AOP的原理流程及原始碼解析(一)

在Spring的配置類上添加註解@EnableAspectJAutoProxy:

@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class MvcContextConfig extends WebMvcConfigurerAdapter {

}

Spring在解析此類時,會解析類上的所有註解,如果這個註解是一個合成註解,合成的註解元素中含有Spring內有特殊作用的註解,則會遞迴的解析。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class) public @interface EnableAspectJAutoProxy { /** * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed * to standard Java interface-based proxies. The default is {@code false}. */ boolean proxyTargetClass() default
false; /** * Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal} * for retrieval via the {@link org.springframework.aop.framework.AopContext} class. * Off by default, i.e. no guarantees that {@code AopContext} access will work. * @since 4.3.1 */
boolean exposeProxy() default false; }

EnableAspectJAutoProxy 的元註解中含有@Import註解,此註解在Spring容器中負責引入一個類,此類若是一個普通的類,則當做一個Bean,和@ComponentScan掃描註解生成的Bean一樣;若是一個ImportSelecter,則從幾個類中篩選出一個類,返回其全名,到時候生成此Bean;若引入的是一個ImportBeanDefinitionRegistrar的實現類,則能夠手動根據註解的資訊註冊BeanDefinition,到時候生成Bean。

@EnableAspectJAutoProxy 的元註解中含有@Import,引入了一個ImportBeanDefinitionRegistrar的實現類AspectJAutoProxyRegistrar:

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

    /**
     * Register, escalate, and configure the AspectJ auto proxy creator based on the value
     * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
     * {@code @Configuration} class.
     */
    @Override
    public void registerBeanDefinitions(
            AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

        //註冊一個AOP代理實現的Bean
        AnnotationAttributes enableAspectJAutoProxy =
                AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
        if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
        }
        if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
            AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
        }
    }

}

AspectJAutoProxyRegistrar 根據註解@EnableAspectJAutoProxy上的屬性來註冊相應的Bean,proxyTargetClass = true 指定使用CGLIB來作為AOP的代理實現方式。若不設定此屬性,則預設使用jdk proxy作為代理實現方式。他們兩者的區別是: jdk動態代理只支援介面的方法代理,不支援類自身的方法,它動態地生成一個代理類,繼承自Proxy,實現被代理的介面,內部持有被代理物件;而CGLIB則支援所有的方法代理,它動態生成一個代理類,繼承自被代理類,所以叫TargetClass。

public abstract class AopConfigUtils {

    //有三種AOP的配置形式,有基於Spring內建的,有基於使用者配置檔案的,有基於註解的,基於註解的優先順序最高,
    //一般配置一種就可以,如果配置多種則優先順序高的會覆蓋優先順序低的
    static {
        APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
        APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
        APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
    }

    public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
        return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
    }
    //註冊AnnotationAwareAspectJAutoProxyCreator到容器中,此類負責基於註解的AOP動態代理實現
    public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
        return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
    }
    //設定支援類的代理,設定此屬性到時候會使用CGLIB來生成動態代理類
    public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
        if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
            BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
            definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
        }
    }


    private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
            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) { 
                    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);
        registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
        return beanDefinition;
    }


}