源码解读系列-spring源码(十三)- 创建 AOP 代理的解析I

AnnotationAwareAspectJAutoProxyCreator类图

AnnotationAwareAspectJAutoProxyCreator 实现了几个重要的扩展接口(可能是在父类中实现):

1)实现了 BeanPostProcessor 接口:实现了 postProcessAfterInitialization 方法。

2)实现了 InstantiationAwareBeanPostProcessor 接口:实现了 postProcessBeforeInstantiation 方法。

3)实现了 SmartInstantiationAwareBeanPostProcessor 接口:实现了 predictBeanType 方法、getEarlyBeanReference 方法。

4)实现了 BeanFactoryAware 接口,实现了 setBeanFactory 方法。

对于 AOP 来说,postProcessAfterInitialization 是我们重点分析的内容,因为在该方法中,会对 bean 进行代理,该方法由父类 AbstractAutoProxyCreator 实现。

AbstractAutoProxyCreator#postProcessAfterInitialization
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        // 1.判断当前bean是否需要被代理,如果需要则进行封装
        if (!this.earlyProxyReferences.contains(cacheKey)) {
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

1.判断当前bean是否需要被代理,如果需要则进行封装,见代码块1。

代码块1:wrapIfNecessary
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    // 1.判断当前bean是否在targetSourcedBeans缓存中存在(已经处理过),如果存在,则直接返回当前bean
    if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
        return bean;
    }
    // 2.在advisedBeans缓存中存在,并且value为false,则代表无需处理
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    }
    // 3.bean的类是aop基础设施类 || bean应该跳过,则标记为无需处理,并返回
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }
 
    // Create proxy if we have advice.
    // 4.获取当前bean的Advices和Advisors
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    // 5.如果存在增强器则创建代理
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        // 5.1 创建代理对象:这边SingletonTargetSource的target属性存放的就是我们原来的bean实例(也就是被代理对象),
        // 用于最后增加逻辑执行完毕后,通过反射执行我们真正的方法时使用(method.invoke(bean, args))
        Object proxy = createProxy(
                bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        // 5.2 创建完代理后,将cacheKey -> 代理类的class放到缓存
        this.proxyTypes.put(cacheKey, proxy.getClass());
        // 返回代理对象
        return proxy;
    }
    // 6.标记为无需处理
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
}

4.获取当前 bean 的 Advices 和 Advisors,见代码块2。

5.1 创建代理对象,见代码块14。

代码块2:getAdvicesAndAdvisorsForBean
@Override
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
    // 1.找到符合条件的Advisor
    List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
    if (advisors.isEmpty()) {
        // 2.如果没有符合条件的Advisor,则返回null
        return DO_NOT_PROXY;
    }
    return advisors.toArray();
}

1.找到符合条件的 Advisor,见代码块3。

代码块3:findEligibleAdvisors
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    // 1.查找所有的候选Advisor
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    // 2.从所有候选的Advisor中找出符合条件的
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    // 3.扩展方法,留个子类实现
    extendAdvisors(eligibleAdvisors);
    if (!eligibleAdvisors.isEmpty()) {
        // 4.对符合条件的Advisor进行排序
        eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    return eligibleAdvisors;
}

1.查找所有的候选 Advisor,见代码块4。

2.从所有候选的 Advisor 中找出符合条件的,见代码块13。

代码块4:findAdvisorBeans
@Override
protected List<Advisor> findCandidateAdvisors() {
    // 1.添加根据父类规则找到的所有advisor。
    List<Advisor> advisors = super.findCandidateAdvisors();
    // 2.为bean工厂中的所有AspectJ方面构建advisor
    advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    return advisors;
}

1.添加根据父类规则找到的所有 advisor,见代码块5。

2.为 bean 工厂中的所有 AspectJ 方面构建 advisor,见代码块6。

代码块5:findCandidateAdvisors
protected List<Advisor> findCandidateAdvisors() {
    return this.advisorRetrievalHelper.findAdvisorBeans();
}
 
public List<Advisor> findAdvisorBeans() {
    // 1.确认advisor的beanName列表,优先从缓存中拿
    String[] advisorNames = null;
    synchronized (this) {
        advisorNames = this.cachedAdvisorBeanNames;
        if (advisorNames == null) {
            //  1.1 如果缓存为空,则获取class类型为Advisor的所有bean名称
            advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                    this.beanFactory, Advisor.class, true, false);
            this.cachedAdvisorBeanNames = advisorNames;
        }
    }
    if (advisorNames.length == 0) {
        return new LinkedList<Advisor>();
    }
 
    // 2.遍历处理advisorNames
    List<Advisor> advisors = new LinkedList<Advisor>();
    for (String name : advisorNames) {
        if (isEligibleBean(name)) {
            // 2.1 跳过当前正在创建的advisor
            if (this.beanFactory.isCurrentlyInCreation(name)) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Skipping currently created advisor '" + name + "'");
                }
            } else {
                try {
                    // 2.2 通过beanName获取对应的bean对象,并添加到advisors
                    advisors.add(this.beanFactory.getBean(name, Advisor.class));
                } catch (BeanCreationException ex) {
                    Throwable rootCause = ex.getMostSpecificCause();
                    if (rootCause instanceof BeanCurrentlyInCreationException) {
                        BeanCreationException bce = (BeanCreationException) rootCause;
                        if (this.beanFactory.isCurrentlyInCreation(bce.getBeanName())) {
                            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;
                }
            }
        }
    }
    // 3.返回符合条件的advisor列表
    return advisors;
}
代码块6:buildAspectJAdvisors
public List<Advisor> buildAspectJAdvisors() {
    List<String> aspectNames = this.aspectBeanNames;
    // 1.如果aspectNames为空,则进行解析
    if (aspectNames == null) {
        synchronized (this) {
            aspectNames = this.aspectBeanNames;
            if (aspectNames == null) {
                List<Advisor> advisors = new LinkedList<Advisor>();
                aspectNames = new LinkedList<String>();
                // 1.1 获取所有的beanName
                String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                        this.beanFactory, Object.class, true, false);
                // 1.2 循环遍历所有的beanName,找出对应的增强方法
                for (String beanName : beanNames) {
                    // 1.3 不合法的beanName则跳过,默认返回true,子类可以覆盖实现,AnnotationAwareAspectJAutoProxyCreator
                    // 实现了自己的逻辑,支持使用includePatterns进行筛选
                    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.
                    // 获取beanName对应的bean的类型
                    Class<?> beanType = this.beanFactory.getType(beanName);
                    if (beanType == null) {
                        continue;
                    }
                    // 1.4 如果beanType存在Aspect注解则进行处理
                    if (this.advisorFactory.isAspect(beanType)) {
                        // 将存在Aspect注解的beanName添加到aspectNames列表
                        aspectNames.add(beanName);
                        // 新建切面元数据
                        AspectMetadata amd = new AspectMetadata(beanType, beanName);
                        // 获取per-clause的类型是SINGLETON
                        if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                            // 使用BeanFactory和beanName创建一个BeanFactoryAspectInstanceFactory,主要用来创建切面对象实例
                            MetadataAwareAspectInstanceFactory factory =
                                    new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
                            // 1.5 解析标记AspectJ注解中的增强方法
                            List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
                            // 1.6 放到缓存中
                            if (this.beanFactory.isSingleton(beanName)) {
                                // 如果beanName是单例则直接将解析的增强方法放到缓存
                                this.advisorsCache.put(beanName, classAdvisors);
                            } else {
                                // 如果不是单例,则将factory放到缓存,之后可以通过factory来解析增强方法
                                this.aspectFactoryCache.put(beanName, factory);
                            }
                            // 1.7 将解析的增强器添加到advisors
                            advisors.addAll(classAdvisors);
                        } else {
                            // 如果per-clause的类型不是SINGLETON
                            // Per target or per this.
                            if (this.beanFactory.isSingleton(beanName)) {
                                // 名称为beanName的Bean是单例,但切面实例化模型不是单例,则抛异常
                                throw new IllegalArgumentException("Bean with name '" + beanName +
                                        "' is a singleton, but aspect instantiation model is not singleton");
                            }
                            MetadataAwareAspectInstanceFactory factory =
                                    new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
                            // 将factory放到缓存,之后可以通过factory来解析增强方法
                            this.aspectFactoryCache.put(beanName, factory);
                            // 解析标记AspectJ注解中的增强方法,并添加到advisors中
                            advisors.addAll(this.advisorFactory.getAdvisors(factory));
                        }
                    }
                }
                // 1.9 将解析出来的切面beanName放到缓存aspectBeanNames
                this.aspectBeanNames = aspectNames;
                // 1.10 最后返回解析出来的增强器
                return advisors;
            }
        }
    }
    // 2.如果aspectNames不为null,则代表已经解析过了,则无需再次解析
    // 2.1 如果aspectNames是空列表,则返回一个空列表。空列表也是解析过的,只要不是null都是解析过的。
    if (aspectNames.isEmpty()) {
        return Collections.emptyList();
    }
    // 2.2 aspectNames不是空列表,则遍历处理
    List<Advisor> advisors = new LinkedList<Advisor>();
    for (String aspectName : aspectNames) {
        // 根据aspectName从缓存中获取增强器
        List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
        if (cachedAdvisors != null) {
            // 根据上面的解析,可以知道advisorsCache存的是已经解析好的增强器,直接添加到结果即可
            advisors.addAll(cachedAdvisors);
        } else {
            // 如果不存在于advisorsCache缓存,则代表存在于aspectFactoryCache中,
            // 从aspectFactoryCache中拿到缓存的factory,然后解析出增强器,添加到结果中
            MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
            advisors.addAll(this.advisorFactory.getAdvisors(factory));
        }
    }
    // 返回增强器
    return advisors;
}

1.5 解析标记 AspectJ 注解中的增强方法,见代码块7。

代码块7:getAdvisors
@Override
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
    // 1.前面我们将beanClass和beanName封装成了aspectInstanceFactory的AspectMetadata属性,
    // 这边可以通过AspectMetadata属性重新获取到当前处理的切面类
    Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
    // 2.获取当前处理的切面类的名字
    String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
    // 3.校验切面类
    validate(aspectClass);
 
    // We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
    // so that it will only instantiate once.
    // 4.使用装饰器包装MetadataAwareAspectInstanceFactory,以便它只实例化一次。
    MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
            new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
 
    List<Advisor> advisors = new LinkedList<Advisor>();
    // 5.获取切面类中的方法(也就是我们用来进行逻辑增强的方法,被@Around、@After等注解修饰的方法,使用@Pointcut的方法不处理)
    for (Method method : getAdvisorMethods(aspectClass)) {
        // 6.处理method,获取增强器
        Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
        if (advisor != null) {
            // 7.如果增强器不为空,则添加到advisors
            advisors.add(advisor);
        }
    }
 
    // If it's a per target aspect, emit the dummy instantiating aspect.
    if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
        // 8.如果寻找的增强器不为空而且又配置了增强延迟初始化,那么需要在首位加入同步实例化增强器(用以保证增强使用之前的实例化)
        Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
        advisors.add(0, instantiationAdvisor);
    }
 
    // Find introduction fields.
    // 9.获取DeclareParents注解
    for (Field field : aspectClass.getDeclaredFields()) {
        Advisor advisor = getDeclareParentsAdvisor(field);
        if (advisor != null) {
            advisors.add(advisor);
        }
    }
 
    return advisors;
}

6.处理 method,获取增强器,见代码块8。

代码块8:getAdvisor
@Override
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
                          int declarationOrderInAspect, String aspectName) {
    // 1.校验切面类
    validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
    // 2.AspectJ切点信息的获取(例如:表达式),就是指定注解的表达式信息的获取,如:@Around("execution(* com.itheima.open.aop.*.*(..))")
    AspectJExpressionPointcut expressionPointcut = getPointcut(
            candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
    // 3.如果expressionPointcut为null,则直接返回null
    if (expressionPointcut == null) {
        return null;
    }
    // 4.根据切点信息生成增强器
    return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
            this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}

2.AspectJ 切点信息的获取,见代码块9。

4.根据切点信息生成增强器,见代码块11。

代码块9:getPointcut
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
    // 1.查找并返回给定方法的第一个AspectJ注解(@Before, @Around, @After, @AfterReturning, @AfterThrowing, @Pointcut)
    // 因为我们之前把@Pointcut注解的方法跳过了,所以这边必然不会获取到@Pointcut注解
    AspectJAnnotation<?> aspectJAnnotation =
            AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
    // 2.如果方法没有使用AspectJ的注解,则返回null
    if (aspectJAnnotation == null) {
        return null;
    }
    // 3.使用AspectJExpressionPointcut实例封装获取的信息
    AspectJExpressionPointcut ajexp =
            new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
    // 提取得到的注解中的表达式,
    // 例如:@Around("execution(* com.itheima.open.aop.*.*(..))"),得到:execution(* com.itheima.open.aop.*.*(..))
    ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
    ajexp.setBeanFactory(this.beanFactory);
    return ajexp;
}

1.获取方法上的AspectJ注解,见代码块10。

代码块10:findAspectJAnnotationOnMethod
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
    // 设置要查找的注解类
    Class<?>[] classesToLookFor = new Class<?>[]{
            Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};
    for (Class<?> c : classesToLookFor) {
        // 查找方法上是否存在当前遍历的注解,如果有则返回
        AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) c);
        if (foundAnnotation != null) {
            return foundAnnotation;
        }
    }
    return null;
}

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值