基于注解的SpringAOP源码解析(二)

本文深入探讨SpringAOP中基于注解的增强处理,主要涉及 AnnotationAwareAspectJAutoProxyCreator 类如何在bean实例化前后进行增强。文章详细解释了shouldSkip方法的作用,以及buildAspectJAdvisors方法如何从@Aspect注解的类中获取相关信息,生成增强。此外,还介绍了InstantiationModelAwarePointcutAdvisorImpl构造方法的参数校验和绑定过程。
摘要由CSDN通过智能技术生成

上篇文章中我们搭建了一个阅读源码的demo工程,然后简单介绍了一下@EnableAspectJAutoProxy注解,这个注解最重要的功能就是为向Spring中注入了一个beanAnnotationAwareAspectJAutoProxyCreator,本篇文章就继续来撸AOP的源码

前文已经简单提到了这个类的功能,不过这里还是要先看一下这个类的继承图观察类图可知,AnnotationAwareAspectJAutoProxyCreator这个类间接实现了BeanPostProcessor接口。还记得我们之前在对SpringIOC的源码进行解析时提到过,Spring在实例化Bean的前后会分别调用方法postProcessBeforeInstantiationpostProcessAfterInstantiation而AOP的整体逻辑就是通过这两个方法来实现的

postProcessBeforeInstantiation

首先看一下这个postProcessBeforeInstantiation方法,它是在bean实例化之前调用的,主要是针对切面类。这个方法不在AnnotationAwareAspectJAutoProxyCreator这个类中,而是在其父类AbstractAutoProxyCreator中

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        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;
            }
        }

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

加载增强

上方代码中最重要的一个方法就是shouldSkip方法了,这个方法被AspectJAwareAdvisorAutoProxyCreator所重载

protected boolean shouldSkip(Class<?> beanClass, String beanName) {
  
    //查找所有标识了@Aspect注解的类,这里是重点,接着往下看
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    for (Advisor advisor : candidateAdvisors) {
        if (advisor instanceof AspectJPointcutAdvisor) {
            if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
                return true;
            }
        }
    }
    return super.shouldSkip(beanClass, beanName);
    }


    protected List<Advisor> findCandidateAdvisors() {
        return this.advisorRetrievalHelper.findAdvisorBeans();
    }
    
    protected List<Advisor> findCandidateAdvisors() {
        List<Advisor> advisors = super.findCandidateAdvisors();
        //buildAspectJAdvisors是重点
           advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
        return advisors;
    }

一个长方法buildAspectJAdvisors

    public List<Advisor> buildAspectJAdvisors() {
    //所有Aspect类的名称集合
        List<String> aspectNames = this.aspectBeanNames;
        if (aspectNames == null) {
            synchronized (this) {
                aspectNames = this.aspectBeanNames;
                //这个双重检查是不是在学习安全的单例模式的时候见过
                if (aspectNames == null) {
                    List<Advisor> advisors = new LinkedList<Advisor>();
                    aspectNames = new LinkedList<String>();
                    //获取所有Bean名称
                    String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                            this.beanFactory, Object.class, true, false);
                    for (String beanName : beanNames) {
                        //判断是否符合条件,比如说有时会排除一些类,不让这些类注入进Spring
                        if (!isEligibleBean(beanName)) {
                            continue;
                        }
               
                        Class<?> beanType = this.beanFactory.getType(beanName);
                        if (beanType == null) {
                            continue;
                        }
                        //判断Bean的Class上是否标识@Aspect注解
                        if (this.advisorFactory.isAspect(beanType)) {
                            aspectNames.add(beanName);
                            AspectMetadata amd = new AspectMetadata(beanType, beanName);
                            if (amd.getAjType().getPerClause().getKind() =
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值