Spring源码分析spring源码首页推荐

Spring源码-AOP(五)-AOP核心组件的注册

2017-09-05  本文已影响84人  阿亮私语

前言

上一篇已经说过AOP的入口是BeanDefinition。在<aop:aspectj-autoproxy>中,解析的是AopNamespaceHandler类,我们对 AopNamespaceHandler 类进行分析。

AspectJAutoProxyBeanDefinitionParser

我们发现有这样一段代码

registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());

也就是说AspectJAutoProxyBeanDefinitionParser这个类会去解析<aop:aspectj-autoproxy>标签,进入到该类中发现它也是BeanDefinitionParser的实现类,而所有BeanDefinitionParser的实现类都是从parse()开始入口的。那么我们接下来看看这个类
【AspectJAutoProxyBeanDefinitionParser】

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


其中的registerAspectJAnnotationAutoProxyCreatorIfNecessary()方法是实现注册AnnotationAwareAspectJAutoProxyCreator的地方,也是AOP注册逻辑的主要逻辑。
【AOPNameSpaceUtils】

public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
        ParserContext parserContext, Element sourceElement) {
    /**
     * 1、注册或者升级AutoProxyCreator
     * 2、定义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);
}

1、注册AnnotationAwareAspectJAutoProxyCreator

我们进入到registerAspectJAnnotationAutoProxyCreatorIfNecessary()方法内部

/**
 * 1、实现了自动注册AnnotationAwareAspectJAutoProxyCreator类的功能
 * 2、处理优先级问题,如果已经存在了自动代理创建器,且已经存在的自动代理创建器与现在的不一致,
 * 那么需要根据优先级来判断到底需要使用哪个
 */
@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的ckassName属性(改变bean最重要的就是改变该属性)
                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;
}

2、属性处理

回到registerAspectJAnnotationAutoProxyCreatorIfNecessary()方法中继续接下来的分析useClassProxyingIfNecessary()方法,这里是对proxy-target-class及expose-proxy属性的处理。
【AopNamespaceUtils】

/**
 * 该方法实现了对proxy-target-class属性以及expose-proxy 属性的处理
 * @param registry
 * @param sourceElement
 */
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) {
    if (sourceElement != null) {
        //对于proxy-target-class属性的处理
        boolean proxyTargetClass = Boolean.valueOf(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
        if (proxyTargetClass) {
            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
        }
        //对于expose-proxy属性的处理
        boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
        if (exposeProxy) {
            //强制使用,也是属性设置的一种方式
            AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
        }
    }
}

AopConfigUtils中的强制设置

public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
    if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
        BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
        definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
    }
}

在此处两个属性的作用如下:

上一篇下一篇

猜你喜欢

热点阅读