Spring源码阅读(六)—AOP获取增强

Spring AOP增强获取解析
本文解析了Spring AOP功能的实现流程,重点分析了AOP自定义标签解析及增强获取的过程。从XML配置文件的aop标签解析开始,详细介绍了如何注册AnnotationAwareAspectJAutoProxyCreator,并在创建bean实例前尝试创建代理。

Spring源码阅读(六)—AOP获取增强

本文主要分析了AOP功能实现中的自定义标签解析和增强的获取

个人主页:tuzhenyu’s page
原文地址:Spring源码阅读(六)—AOP获取增强

(0) Spring AOP实现的主要步骤

  • 解析AOP自定义标签,注册AnnotationAwareAspectJAutoProxyCreator自动代理创建器

  • 获取增强

  • 创建代理

(1) 解析AOP自定义标签

  • AOP功能实现的最基本入口在XML配置文件中的AOP功能的开启;
<aop:aspectj-autoproxy>
  • 在容器初始化解析XML配置文件会将标签分为普通标签和自定义标签分别进行解析处理.
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {

    if (delegate.isDefaultNamespace(root)) {

        NodeList nl = root.getChildNodes();

        for (int i = 0; i < nl.getLength(); i++) {

            Node node = nl.item(i);

            if (node instanceof Element) {

                Element ele = (Element) node;

                if (delegate.isDefaultNamespace(ele)) {

                    parseDefaultElement(ele, delegate);

                }

                else {

                    delegate.parseCustomElement(ele);

                }

            }

        }

    }

    else {

        delegate.parseCustomElement(root);

    }

}
  • aop标签属于自定义标签会调用相应的处理器进行处理
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {

    String namespaceUri = getNamespaceURI(ele);

    NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);

    if (handler == null) {

        error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);

        return null;

    }

    return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));

}
  • 从NamespaceHandler中获取aop的aspectj-autoproxy对应的解析器是AspectJAutoProxyBeanDefinitionParser
public void init() {
    this.registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
    this.registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
    this.registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
    this.registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
  • 所有解析器都是由 BeanDefinitionParser 接口的统一实现,入口都是从 parse函数开始的
public BeanDefinition parse(Element element, ParserContext parserContext) {    

    AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);       

    extendBeanDefinition(element, parserContext);   

    return null; 

}
  • registerAspectJAnnotationAutoProxyCreatorIfNecessary 函数是 AnnotationAwareAspectJAutoProxyCreator 注册的地方,也是注册的主要逻辑实现的地方。主要实现了一下三个功能:

    • AnnotationAwareAspectJAutoProxyCreator的注册或升级

    • 对于 proxy-target-class 以及 expose-proxy 属性的处理,用于判断是否强制使用CGLIB代理模式

    • 注册组件并通知,便于监听器作进一步处理.

public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) {
    BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext.getRegistry(), parserContext.extractSource(sourceElement));
    useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
    registerComponentIfNecessary(beanDefinition, parserContext);
}
  • 至此,aop自定义标签完成了解析,同时也将AnnotationAwareAspectJAutoProxyCreator注册到了处理器中.

(2) AOP代理实现的入口

  • spring 容器启动,在每个bean实例话过程中会首先尝试到缓存中获取,获取上失败后会调用createBean()方法从头创建bean.在调用doCreateBean()方法正式创建之前会调用resolveBeforeInstantiation()方法尝试是否创建代理类替代真正的实例,如果创建成功则直接返回跳过后续的真正创建过程,如果创建失败则继续创建bean实例.
Object beanInstance;
try {
    beanInstance = this.resolveBeforeInstantiation(beanName, mbd);
    if(beanInstance != null) {
        return beanInstance;
    }
} catch (Throwable var6) {
    throw new BeanCreationException(mbd.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var6);
}
  • 在resolveBeforeInstantiation()方法中会调用提前注册的处理器AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization()方法实现代理的创建
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    Object bean = null;
    if(!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
        if(!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
            Class targetType = this.determineTargetType(beanName, mbd, new Class[0]);
            if(targetType != null) {
                bean = this.applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                if(bean != null) {
                    bean = this.applyBeanPostProcessorsAfterInitialization(bean, beanName);
                }
            }
        }

        mbd.beforeInstantiationResolved = Boolean.valueOf(bean != null);
    }

    return bean;
}
  • postProcessAfterInitialization()方法调用wrapIfNecessary()方法进行代理的实现
public Object <strong>postProcessAfterInitialization</strong>(Object bean, String beanName) throws BeansException {

        if (bean != null) {

            Object cacheKey = getCacheKey(bean.getClass(), beanName);

            if (!this.earlyProxyReferences.containsKey(cacheKey)) {

                return wrapIfNecessary(bean, beanName, cacheKey);

            }

        }

        return bean;

    }
  • wrapIfNecessary()方法实现了aop实现的主要逻辑,调用getAdvicesAndAdvisorsForBean()提取当前bean 的所有增强方法,然后调用createProxy()方法创建具体代理.
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {

        if (beanName != null && this.targetSourcedBeans.containsKey(beanName)) {

            return bean;

        }

        if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {

            return bean;

        }

        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {

            this.advisedBeans.put(cacheKey, Boolean.FALSE);

            return bean;

        }

        Object[] specificInterceptors = <strong>getAdvicesAndAdvisorsForBean</strong>(bean.getClass(), beanName, null);

        if (specificInterceptors != DO_NOT_PROXY) {

            this.advisedBeans.put(cacheKey, Boolean.TRUE);

            Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));

            this.proxyTypes.put(cacheKey, proxy.getClass());

            return proxy;

        }

        this.advisedBeans.put(cacheKey, Boolean.FALSE);

        return bean;

    }    

(3) AOP增强的获取

  • getAdvicesAndAdvisorsForBean()主要是通过调用findEligibleAdvisors()方法用来获取该bean的增强列表.主要步骤包括:

    • 寻找所有增强

    • 从所有增强中获取适合该bean的增强.

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;

}
  • findCandidateAdvisors()方法是用来获取所有的增强,主要步骤包括:

    • 获取所有在beanFactory中注册的beanName

    • 遍历所有的beanName,判断是否为声明为AspectJ的类,如果是则进行进一步处理

    • 对标记为AspectJ注解的类进行增强器的提取

    • 将提取结果放入缓存

protected List<Advisor> findCandidateAdvisors() {
    List advisors = super.findCandidateAdvisors();
    advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    return advisors;
}
public List<Advisor> buildAspectJAdvisors() {
    List aspectNames = null;
    synchronized(this) {
        aspectNames = this.aspectBeanNames;
        if(aspectNames == null) {
            LinkedList var16 = new LinkedList();
            LinkedList var15 = new LinkedList();
            String[] var17 = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);
            String[] var18 = var17;
            int var19 = var17.length;

            for(int var7 = 0; var7 < var19; ++var7) {
                String beanName = var18[var7];
                if(this.isEligibleBean(beanName)) {
                    Class beanType = this.beanFactory.getType(beanName);
                    if(beanType != null && this.advisorFactory.isAspect(beanType)) {
                        var15.add(beanName);
                        AspectMetadata amd = new AspectMetadata(beanType, beanName);
                        if(amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                            BeanFactoryAspectInstanceFactory factory1 = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
                            List classAdvisors = this.advisorFactory.getAdvisors(factory1);
                            if(this.beanFactory.isSingleton(beanName)) {
                                this.advisorsCache.put(beanName, classAdvisors);
                            } else {
                                this.aspectFactoryCache.put(beanName, factory1);
                            }

                            var16.addAll(classAdvisors);
                        } else {
                            if(this.beanFactory.isSingleton(beanName)) {
                                throw new IllegalArgumentException("Bean with name \'" + beanName + "\' is a singleton, but aspect instantiation model is not singleton");
                            }

                            PrototypeAspectInstanceFactory var20 = new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
                            this.aspectFactoryCache.put(beanName, var20);
                            var16.addAll(this.advisorFactory.getAdvisors(var20));
                        }
                    }
                }
            }

            this.aspectBeanNames = var15;
            return var16;
        }
    }
  • 调用findAdvisorsThatCanApply()方法从所有增强中获取适合该bean的增强
protected List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
    ProxyCreationContext.setCurrentProxiedBeanName(beanName);

    List var4;
    try {
        var4 = AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
    } finally {
        ProxyCreationContext.setCurrentProxiedBeanName((String)null);
    }

    return var4;
}

(4) 总结

AOP功能的实现是从XML配置文件中的aop标签解析开始的,标签的解析会注册代理自动创建器用于后续的调用.当从容器中尝试获取bean的时候会在真正创建bean之前尝试创建代理,创建代理主要包括增强的获取和代理的创建两部分,这篇博文主要分析了增强获取的主要流程.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值