美文网首页
spring AOP 注解式 原理解析

spring AOP 注解式 原理解析

作者: lotusfan2018 | 来源:发表于2018-07-28 17:51 被阅读0次

    开启注解需要在application.xml里配置<aop:aspectj-autoproxy/>
    这个标签是spring AOP自定义的一个标签。我们从<aop:aspectj-autoproxy/>标签的解析入手,来分析 spring 对于注解实现AOP的装配过程和运行机制

    <aop:aspectj-autoproxy/>标签解析

    AopNamespaceHandler是解析AOP标签的入口,我们可以只关注第二个注册了一个,解析“aspectj-autoproxy”标签的AspectJAutoProxyBeanDefinitionParser解析器。

    源码&&方法调用:

    AopNamespaceHandler:

    @Override
    public void init() {
        // In 2.0 XSD as well as in 2.1 XSD.
        registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
        registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
        registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
            
        // Only in 2.0 XSD: moved to context namespace as of 2.1
        registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
    }   
    

    AspectJAutoProxyBeanDefinitionParser:

    /**
    parse方法的调用,是spring BeanDefinitionParser自定义标签的实现
    */
    @Override
    @Nullable
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
        extendBeanDefinition(element, parserContext);
        return null;
    }
    

    AopNamespaceUtils:

    public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
                ParserContext parserContext, Element sourceElement) {
    
            BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
                    parserContext.getRegistry(), parserContext.extractSource(sourceElement));
            useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
            registerComponentIfNecessary(beanDefinition, parserContext);
        }
    

    AopConfigUtils:

    /**
    注册AnnotationAwareAspectJAutoProxyCreator.class
    */
    @Nullable
    public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,
            @Nullable Object source) {
    
        return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
    }
    
    @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)) {
            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;
        }
        //注册bean
        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;
    }
    

    BeanDefinition中Role的定义值:
    beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE)

    /** 用户定义的bean
     * Role hint indicating that a {@code BeanDefinition} is a major part
     * of the application. Typically corresponds to a user-defined bean.
     */
    int ROLE_APPLICATION = 0;
    
    /** 某些复杂的配置
     * Role hint indicating that a {@code BeanDefinition} is a supporting
     * part of some larger configuration, typically an outer
     * {@link org.springframework.beans.factory.parsing.ComponentDefinition}.
     * {@code SUPPORT} beans are considered important enough to be aware
     * of when looking more closely at a particular
     * {@link org.springframework.beans.factory.parsing.ComponentDefinition},
     * but not when looking at the overall configuration of an application.
     */
    int ROLE_SUPPORT = 1;
    
    /** 完全内部使用
     * Role hint indicating that a {@code BeanDefinition} is providing an
     * entirely background role and has no relevance to the end-user. This hint is
     * used when registering beans that are completely part of the internal workings
     * of a {@link org.springframework.beans.factory.parsing.ComponentDefinition}.
     */
    int ROLE_INFRASTRUCTURE = 2;
    

    至此spring通过对<aop:aspectj-autoproxy/>的解析,在容器中注册了一个beanName为org.springframework.aop.config.internalAutoProxyCreator,类为AnnotationAwareAspectJAutoProxyCreator.class ,只供内部使用的bean。

    AnnotationAwareAspectJAutoProxyCreator运行机制

    AnnotationAwareAspectJAutoProxyCreator.png

    从继承的关系分析:
    继承ProxyConfig:spring AOP代理工厂配置
    继承Aware: 回调BeanClassLoaderAware,BeanFactory
    继承BeanProcessor: 后置处理器;bean初始化前、后 aop逻辑的实现(重点)
    继承Ordered: Advistor 列表的排序

    AOP的装配过程是从bean初始化调用postProcessBeforeInitialization开始,postProcessAfterInitialization结束的。

    源码&&方法调用:

    AbstractAutoProxyCreator :

    /**
    Bean初始化的前置处理
    对切面类 打标记,如果是spring 基础类(isInfrastructureClass)或 忽略的类(shouldSkip)
    存在advisedBeans列表里为false
    **/
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
            Object cacheKey = getCacheKey(beanClass, beanName);
    
        if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
            if (this.advisedBeans.containsKey(cacheKey)) {
                return null;
            }
            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.
        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;
    }
    
    /**
    统一bean命名的一个规则定义
    **/
    protected Object getCacheKey(Class<?> beanClass, @Nullable String beanName) {
            if (StringUtils.hasLength(beanName)) {
                return (FactoryBean.class.isAssignableFrom(beanClass) ?
                        BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName);
            }
            else {
                return beanClass;
            }
        }
    
    /**
    Bean初始化的后置处理
    */
    @Override
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
        if (bean != null) {
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (!this.earlyProxyReferences.contains(cacheKey)) {
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }
    
    /**
    真正处理AOP的代理生成wrapIfNecessary
    getAdvicesAndAdvisorsForBean是获取符合当前bean的Advistor
    **/
    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;
        }
        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }
        
        // Create proxy if we have advice. 如查有匹配当前bean的advice,则创建代理
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(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;
    }
    

    AbstractAdvisorAutoProxyCreator:

    @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();
    }
    
    /**
    findCandidateAdvisors是获取当前BeanFactory(DefaultListableBeanFactory)的所有Advistor
    findAdvisorsThatCanApply从所有的Advistor中匹配适用当前bean的Advistor
    **/
    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;
    }
    

    AnnotationAwareAspectJAutoProxyCreator:

    /**
    覆写了AbstractAdvisorAutoProxyCreator中的findCandidateAdvisors方法
    获取所有Advistor,在这里就会扫描所有的bean寻找@Aspect类,进一步解析
    **/
    @Override
    protected List<Advisor> findCandidateAdvisors() {
        // Add all the Spring advisors found according to superclass rules.
        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;
    }
    

    AspectJAwareAdvisorAutoProxyCreator:

    /**
     * 覆盖了父类AbstractAdvisorAutoProxyCreator中的extendAdvisors方法
     * Adds an {@link ExposeInvocationInterceptor} to the beginning of the advice chain.
     * These additional advices are needed when using AspectJ expression pointcuts
     * and when using AspectJ-style advice.
     */
    @Override
    protected void extendAdvisors(List<Advisor> candidateAdvisors) {
        AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
    }
    

    AspectJProxyUtils:

    /**
    自动加入 ExposeInvocationInterceptor.ADVISOR 到 advisors chain中
    */
    public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {
        // Don't add advisors to an empty list; may indicate that proxying is just not required
        if (!advisors.isEmpty()) {
            boolean foundAspectJAdvice = false;
            for (Advisor advisor : advisors) {
                // Be careful not to get the Advice without a guard, as
                // this might eagerly instantiate a non-singleton AspectJ aspect
                if (isAspectJAdvice(advisor)) {
                    foundAspectJAdvice = true;
                }
            }
            if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {
                advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
                return true;
            }
        }
        return false;
    }
    

    BeanFactoryAdvisorRetrievalHelper:

    /**
    在缓存中匹配Advistor
    **/
    public List<Advisor> findAdvisorBeans() {
            // Determine list of advisor bean names, if not cached already.
            String[] advisorNames = null;
            synchronized (this) {
                advisorNames = this.cachedAdvisorBeanNames;
                if (advisorNames == null) {
                    // Do not initialize FactoryBeans here: We need to leave all regular beans
                    // uninitialized to let the auto-proxy creator apply to them!
                    advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                            this.beanFactory, Advisor.class, true, false);
                    this.cachedAdvisorBeanNames = advisorNames;
                }
            }
            if (advisorNames.length == 0) {
                return new LinkedList<>();
            }
    
        List<Advisor> advisors = new LinkedList<>();
        for (String name : advisorNames) {
            if (isEligibleBean(name)) {
                if (this.beanFactory.isCurrentlyInCreation(name)) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Skipping currently created advisor '" + name + "'");
                    }
                }
                else {
                    try {
                        advisors.add(this.beanFactory.getBean(name, Advisor.class));
                    }
                    catch (BeanCreationException ex) {
                        Throwable rootCause = ex.getMostSpecificCause();
                        if (rootCause instanceof BeanCurrentlyInCreationException) {
                            BeanCreationException bce = (BeanCreationException) rootCause;
                            String bceBeanName = bce.getBeanName();
                            if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
                                if (logger.isDebugEnabled()) {
                                    logger.debug("Skipping advisor '" + name +
                                            "' with dependency on currently created bean: " + ex.getMessage());
                                }
                                // Ignore: indicates a reference back to the bean we're trying to advise.
                                // We want to find advisors other than the currently created bean itself.
                                continue;
                            }
                        }
                        throw ex;
                    }
                }
            }
        }
        return advisors;
    }
    

    BeanFactoryAspectJAdvisorsBuilder :

        /**
        * 完成@Aspect和 @PointCut的解析,最终生成Advistor
        * Look for AspectJ-annotated aspect beans in the current bean factory,
        * and return to a list of Spring AOP Advisors representing them.
        * <p>Creates a Spring Advisor for each AspectJ advice method.
        * @return the list of {@link org.springframework.aop.Advisor} beans
        * @see #isEligibleBean
        */
        public List<Advisor> buildAspectJAdvisors() {
            List<String> aspectNames = this.aspectBeanNames;
    
            if (aspectNames == null) {
                synchronized (this) {
                    aspectNames = this.aspectBeanNames;
                    if (aspectNames == null) {
                        List<Advisor> advisors = new LinkedList<>();
                        aspectNames = new LinkedList<>();
                        String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                                this.beanFactory, Object.class, true, false);
                        for (String beanName : beanNames) {
                            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.
                            Class<?> beanType = this.beanFactory.getType(beanName);
                            if (beanType == null) {
                                continue;
                            }
                            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);
                                    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 LinkedList<>();
            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;
        }
    

    相关文章

      网友评论

          本文标题:spring AOP 注解式 原理解析

          本文链接:https://www.haomeiwen.com/subject/neoomftx.html