Spring5AOP——AbstractAutoProxyCreator横切逻辑织入目标Bean中

Spring AOP的总体流程

  • 1、注册解析AOP的服务
  • 2、解析和加载横切逻辑
  • 3、将横切逻辑织入目标Bean中

AnnotationAwareAspectJAutoProxyCreator继承体系图

AnnotationAwareAspectJAutoProxyCreator既实现了SmartInstantiationAwareBeanPostProcessor 又实现了BeanFactoryAware。就可以对容器做一些事情。

AnnotationAwareAspectJAutoProxyCreator 实现了Order接口,所以先于普通的BeanPostProcessor注册,并对普通BeanPostProcessor也能起作用。

AnnotationAwareAspectJAutoProxyCreator 是InstantiationAwareBeanPostProcessor,会在Bean被创建之前,在resolveBeforeInstantiation中被调用。

Spring Aop主要是通过AbstractAutoProxyCreator实现的BeanPostProcessor、InstantiationAwareBeanPostProcessor以及SmartInstantiationAwareBeanPostProcessor接口里面的后置处理器方法,来介入到Spring IOC容器的Bean的实例化以及初始化的过程中对Bean进行AOP的处理的。

所以AbstractAutoProxyCreator类里面的实现的容器级别的后置处理器方法便是介入分析的点:

  • 横切逻辑的加载主要是在AbstractAutoProxyCreator类中的postProcessBeforeInstantiation方法中,该方法是在Bean的实例化之前被调用的。
  • 横切逻辑织入目标Bean中主要是在AbstractAutoProxyCreator类中的postProcessAfterInitialization方法中,该方法是在Bean的实例化之后被调用的。
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
        implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {

    //当 Bean 被循环引用, 并且被暴露了,
    // 则会通过 getEarlyBeanReference 来创建代理类;
    // 通过判断 earlyProxyReferences 中
    // 是否存在 beanName 来决定是否需要对 target 进行动态代理
    private final Map<Object, Object> earlyProxyReferences = new ConcurrentHashMap<>(16);

    @Override
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
        if (bean != null) {
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            //当 Bean 被循环引用, 并且被暴露了,
            // 则会通过 getEarlyBeanReference 来创建代理类;
            // 通过判断 earlyProxyReferences 中
            // 是否存在 beanName 来决定是否需要对 target 进行动态代理
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                //该方法将会返回代理类
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }
}

AbstractAutoProxyCreator的postProcessAfterInitialization方法是在AbstractAutowireCapableBeanFactory类中的createBean方法中的创建Bean实例方法doCreateBean方法中的的对bean进行初始化方法initializeBean方法中被最终调用的。

initializeBean

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
        implements AutowireCapableBeanFactory {

    protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
        // 1.激活Aware方法
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                invokeAwareMethods(beanName, bean);
                return null;
            }, getAccessControlContext());
        }
        else {
            invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            // 2.在初始化前应用BeanPostProcessor的postProcessBeforeInitialization方法,允许对bean实例进行包装
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
            // 3.调用初始化方法
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }
        if (mbd == null || !mbd.isSynthetic()) {
            // 4.在初始化后应用BeanPostProcessor的postProcessAfterInitialization方法,允许对bean实例进行包装
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }
        // 5.返回wrappedBean
        return wrappedBean;
    }

    @Override
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
            throws BeansException {

        Object result = existingBean;
        // 1.遍历所有注册的BeanPostProcessor实现类,调用postProcessAfterInitialization方法
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            // 2.在bean初始化后,调用postProcessAfterInitialization方法
            Object current = processor.postProcessAfterInitialization(result, beanName);
            if (current == null) {
                // 3.如果返回null,则不会调用后续的BeanPostProcessors
                return result;
            }
            result = current;
        }
        return result;
    }
}

因为AbstractAutoProxyCreator实现了InstantiationAwareBeanPostProcessor接口,所以,AbstractAutowireCapableBeanFactory类中的initializeBean方法中的applyBeanPostProcessorsAfterInitialization方法中的代码processor.postProcessAfterInitialization(result, beanName)方法最终调用的是AbstractAutoProxyCreator类中的postProcessAfterInitialization方法完成的AOP相关横切逻辑的织入的。

由于动态代理对象的创建,并不需要也不会去干预Bean的实例化、属性赋值以及初始化,而初始化结束才意味着Bean被创建完成,因此Spring会等到Bean初始化之后,也就是执行invokeAwareMethods方法之后,才会将相关的横切逻辑给织入到Bean里面。

通过前面的学习了解到,Spring AOP是通过Bean级别的后置处理器在Bean的生命周期中对Bean进行处理的,而针对Bean初始化完之后在进行介入的点就不是很多了,基本就只剩下applyBeanPostProcessorsAfterInitialization方法里面调用的BeanPostProcessor的postProcessAfterInitialization方法了,事实上Spring AOP也正是在此处对bean进行横切逻辑的织入的。

Spring AOP横切逻辑的织入过程:

getEarlyBeanReference

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
        implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {

    //当 Bean 被循环引用, 并且被暴露了,
    // 则会通过 getEarlyBeanReference 来创建代理类;
    // 通过判断 earlyProxyReferences 中
    // 是否存在 beanName 来决定是否需要对 target 进行动态代理
    private final Map<Object, Object> earlyProxyReferences = new ConcurrentHashMap<>(16);
    
    @Override
    public Object getEarlyBeanReference(Object bean, String beanName) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        this.earlyProxyReferences.put(cacheKey, bean);
        return wrapIfNecessary(bean, beanName, cacheKey);
    }
}

AbstractAutoProxyCreator类中的getEarlyBeanReference方法,是在AbstractAutowireCapableBeanFactory类中的getEarlyBeanReference方法中的exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName)代码处被调用

而AbstractAutowireCapableBeanFactory类中的getEarlyBeanReference方法又是在AbstractAutowireCapableBeanFactory类中的doCreateBean方法中的addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean))代码处被调用,addSingletonFactory()方法是提前暴露Bean用于解决SpringIOC容器Bean的循环依赖问题的。

AbstractAutoProxyCreator横切逻辑织入的入口方法:

  • postProcessAfterInitialization:正常流程的织入入口。
  • getEarlyBeanReference:循环依赖的织入入口。

回到AbstractAutoProxyCreator的postProcessAfterInitialization方法

@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        //当 Bean 被循环引用, 并且被暴露了,
        // 则会通过 getEarlyBeanReference 来创建代理类;
        // 通过判断 earlyProxyReferences 中
        // 是否存在 beanName 来决定是否需要对 target 进行动态代理
        if (this.earlyProxyReferences.remove(cacheKey) != bean) {
            //该方法将会返回代理类
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

如果if (this.earlyProxyReferences.remove(cacheKey) != bean)条件满足

  • 1、remove方法执行后返回null
  • 2、先前发生循环依赖创建出来的Bean与此时完成初始化的Bean不是同一个

满足上面的两种情况之一,都会以此处的bean为准,对其进行后续的动态代理的织入,毕竟此处的bean已经走完正常的实例化、属性赋值以及初始化的流程了,是最接近成功的bean。

wrapIfNecessary

  • 判断当前bean是否需要被代理,如果需要则进行封装
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
        implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {

    /**
     * Spring实现Bean代理的核心方法。wrapIfNecessary在两处会被调用,一处是getEarlyBeanReference,
     * 另一处是postProcessAfterInitialization
     */
    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        //已经被处理过
        // 1.判断当前bean是否在targetSourcedBeans缓存中存在(已经处理过),如果存在,则直接返回当前bean
        if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
            return bean;
        }
        //不需要被织入逻辑的
        // 2.在advisedBeans缓存中存在,并且value为false,则代表无需处理
        if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
            return bean;
        }
        //是不是基础的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.
        // 返回匹配当前Bean的所有Advice\Advisor\Interceptor
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        // 5.如果存在增强器则创建代理
        if (specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
            //创建Bean对应的代理,SingletonTargetSource用于封装实现类的信息
            // 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;
        }
        //该Bean是不需要进行代理的,下次就不需要重复生成了
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }
}

getAdvicesAndAdvisorsForBean

  • 返回匹配当前Bean的所有Advice\Advisor\Interceptor
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {

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

findEligibleAdvisors

  • 找到符合条件的Advisor
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {

    protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
        //找到Spring IoC容器中所有的候选Advisor
        List<Advisor> candidateAdvisors = findCandidateAdvisors();
        //判断找到的Advisor能不能作用到当前的类上
        List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
        extendAdvisors(eligibleAdvisors);
        //对获取到的advisor进行排序
        if (!eligibleAdvisors.isEmpty()) {
            eligibleAdvisors = sortAdvisors(eligibleAdvisors);
        }
        return eligibleAdvisors;
    }
}

findCandidateAdvisors

  • 找到Spring IoC容器中所有的候选Advisor
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {

    protected List<Advisor> findCandidateAdvisors() {
        Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
        return this.advisorRetrievalHelper.findAdvisorBeans();
    }

    public List<Advisor> findAdvisorBeans() {
        // Determine list of advisor bean names, if not cached already.
        // 先尝试从缓存中获取容器中所有 Advisor bean 的名称
        String[] 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!
            // 如果缓存为空,尝试从容器以及其父容器分析得到所有 Advisor bean 的名称
            advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                    this.beanFactory, Advisor.class, true, false);
            // 添加进缓存
            this.cachedAdvisorBeanNames = advisorNames;
        }
        if (advisorNames.length == 0) {
            return new ArrayList<>();
        }

        // 2.遍历处理advisorNames
        List<Advisor> advisors = new ArrayList<>();
        for (String name : advisorNames) {
            if (isEligibleBean(name)) {
                // 创建中的 bean 会被忽略
                // 2.1 跳过当前正在创建的advisor
                if (this.beanFactory.isCurrentlyInCreation(name)) {
                    if (logger.isTraceEnabled()) {
                        logger.trace("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;
                            String bceBeanName = bce.getBeanName();
                            if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
                                if (logger.isTraceEnabled()) {
                                    logger.trace("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;
    }
}

关于AnnotationAwareAspectJAutoProxyCreator类中的findCandidateAdvisors方法的解读

public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {

    private BeanFactoryAspectJAdvisorsBuilder aspectJAdvisorsBuilder;

    @Override
    protected List<Advisor> findCandidateAdvisors() {
        // Add all the Spring advisors found according to superclass rules.
        // 使用注解方式配置AOP的时候还是能够支持对XML配置的AOP的支持的.
        List<Advisor> advisors = super.findCandidateAdvisors();
        // Build Advisors for all AspectJ aspects in the bean factory.
        if (this.aspectJAdvisorsBuilder != null) {
            // 为bean工厂中的所有AspectJ方面构建advisor
            advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
        }
        return advisors;
    }
}

public class BeanFactoryAspectJAdvisorsBuilder {

    private final ListableBeanFactory beanFactory;

    private final AspectJAdvisorFactory advisorFactory;

    @Nullable
    private volatile List<String> aspectBeanNames;

    private final Map<String, List<Advisor>> advisorsCache = new ConcurrentHashMap<>();

    private final Map<String, MetadataAwareAspectInstanceFactory> aspectFactoryCache = new ConcurrentHashMap<>();

    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 ArrayList<>();
                    //用于保存切面的名称的集合
                    aspectNames = new ArrayList<>();
                    //获取所有的beanName
                    // AOP功能中在这里传入的是Object对象,代表去容器中获取到所有的组件的名称,然后再
                    // 进行遍历,这个过程是十分的消耗性能的,所以说Spring会再这里加入了保存切面信息的缓存。
                    String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                            this.beanFactory, Object.class, true, false);
                    //遍历我们从IOC容器中获取处的所有Bean的名称
                    // 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.
                        //获取对应的bean的类型
                        Class<?> beanType = this.beanFactory.getType(beanName);
                        if (beanType == null) {
                            continue;
                        }
                        //提取@Aspect注解标记的Class
                        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);
                                //Aspect里面的advice和pointcut被拆分成一个个的advisor,
                                // advisor里的advice和pointcut是1对1的关系
                                // 1.5 解析标记AspectJ注解中的增强方法
                                List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
                                if (this.beanFactory.isSingleton(beanName)) {
                                    //单例则直接将Advisor类存到缓存
                                    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 ArrayList<>();
        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;
    }
}

更详细的横切逻辑的加载与解析:Spring5AOP——AbstractAutoProxyCreator横切逻辑的加载与解析

回到AbstractAdvisorAutoProxyCreator类的findEligibleAdvisors方法中

findAdvisorsThatCanApply

  • 从所有候选的Advisor中找出符合条件的
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {

    protected List<Advisor> findAdvisorsThatCanApply(
            List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

        //给其ThreadLocal<String>的成员变量 currentProxiedBeanName设置上正在创建动态代理的Bean
        //以标注当前线程正在创建的动态代理是针对哪一个Bean的
        ProxyCreationContext.setCurrentProxiedBeanName(beanName);
        try {
            //委托AopUtils.findAdvisorsThatCanApply方法筛选出匹配Bean的Advisors
            return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
        }
        finally {
            ProxyCreationContext.setCurrentProxiedBeanName(null);
        }
    }
}

public final class ProxyCreationContext {

    private static final ThreadLocal<String> currentProxiedBeanName =
            new NamedThreadLocal<>("Name of currently proxied bean");

    @Nullable
    public static String getCurrentProxiedBeanName() {
        return currentProxiedBeanName.get();
    }

    static void setCurrentProxiedBeanName(@Nullable String beanName) {
        if (beanName != null) {
            currentProxiedBeanName.set(beanName);
        }
        else {
            currentProxiedBeanName.remove();
        }
    }

}

AopUtils.findAdvisorsThatCanApply

  • 委托AopUtils.findAdvisorsThatCanApply方法筛选出匹配Bean的Advisors
public abstract class AopUtils {

    public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
        if (candidateAdvisors.isEmpty()) {
            return candidateAdvisors;
        }
        List<Advisor> eligibleAdvisors = new ArrayList<>();
        for (Advisor candidate : candidateAdvisors) {
            // 1.首先处理引介增强(@DeclareParents)用的比较少可以忽略,有兴趣的参考:21_AOP_Advice增强2(异常、引介)
            //判断Advisor对象是不是实现了IntroductionAdvisor
            if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
                eligibleAdvisors.add(candidate);
            }
        }
        boolean hasIntroductions = !eligibleAdvisors.isEmpty();
        // 2.遍历所有的candidateAdvisors
        for (Advisor candidate : candidateAdvisors) {
            // 2.1 引介增强已经处理,直接跳过
            if (candidate instanceof IntroductionAdvisor) {
                // already processed
                continue;
            }
            // 2.2 正常增强处理,判断当前bean是否可以应用于当前遍历的增强器(bean是否包含在增强器的execution指定的表达式中)
            if (canApply(candidate, clazz, hasIntroductions)) {
                eligibleAdvisors.add(candidate);
            }
        }
        return eligibleAdvisors;
    }
}

AopUtils.canApply

  • 判断当前Advisor的Pointcut是否匹配当前bean
public abstract class AopUtils {

    public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
        //判断是否是IntroductionAdvisor
        if (advisor instanceof IntroductionAdvisor) {
            return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
        }
        //判断是否是PointcutAdvisor
        else if (advisor instanceof PointcutAdvisor) {
            //转为PointcutAdvisor类型
            PointcutAdvisor pca = (PointcutAdvisor) advisor;
            return canApply(pca.getPointcut(), targetClass, hasIntroductions);
        }
        else {
            // It doesn't have a pointcut so we assume it applies.
            //如果Advisor连Pointcut表达式都没有的话,就证明它是匹配所有Bean的
            return true;
        }
    }
}

AopUtils.canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions)

  • canApply(pca.getPointcut(), targetClass, hasIntroductions)
public abstract class AopUtils {

    public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
        Assert.notNull(pc, "Pointcut must not be null");
        //对Bean进行初筛
        if (!pc.getClassFilter().matches(targetClass)) {
            return false;
        }
        //判断如果当前Advisor所指代的方法的切点表达式如果是对任意方法都放行,则直接返回
        MethodMatcher methodMatcher = pc.getMethodMatcher();
        if (methodMatcher == MethodMatcher.TRUE) {
            // No need to iterate the methods if we're matching any method anyway...
            return true;
        }

        // 这里将MethodMatcher强转为IntroductionAwareMethodMatcher类型的原因在于,
        // 如果目标类不包含Introduction类型的Advisor,那么使用
        // IntroductionAwareMethodMatcher.matches()方法进行匹配判断时可以提升匹配的效率,
        // 其会判断目标bean中没有使用Introduction织入新的方法,则可以使用该方法进行静态匹配,从而提升效率
        // 因为Introduction类型的Advisor可以往目标类中织入新的方法,新的方法也可能是被AOP环绕的方法
        // IntroductionAwareMethodMatcher的主要实现类是AspectJExpressionPointcut,可以看看里面的实现
        IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
        //判断匹配器是不是IntroductionAwareMethodMatcher
        if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
            introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
        }

        Set<Class<?>> classes = new LinkedHashSet<>();
        //判断当前class是不是代理的class对象
        if (!Proxy.isProxyClass(targetClass)) {
            classes.add(ClassUtils.getUserClass(targetClass));
        }
        //获取到targetClass所实现的接口的class对象,然后加入到集合中
        classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

        for (Class<?> clazz : classes) {
            Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
            for (Method method : methods) {
                //通过methodMatcher.matches来匹配方法
                if (introductionAwareMethodMatcher != null ?
                        introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
                        //通过方法匹配器进行匹配
                        methodMatcher.matches(method, targetClass)) {
                    return true;
                }
            }
        }

        return false;
    }
}

matches

  • !pc.getClassFilter().matches(targetClass)
  • 对Bean进行初筛
public class AspectJExpressionPointcut extends AbstractExpressionPointcut
        implements ClassFilter, IntroductionAwareMethodMatcher, BeanFactoryAware {

    @Override
    public boolean matches(Class<?> targetClass) {
        //获取类里的pointcut表达式
        PointcutExpression pointcutExpression = obtainPointcutExpression();
        try {
            try {
                //对被代理对象做类级别的初筛,只能匹配部分表达式(如within),
                //不支持execution等表达式的部分写法
                //对于精确到类上的execution表达式,该方法是支持精准匹配的
                return pointcutExpression.couldMatchJoinPointsInType(targetClass);
            }
            catch (ReflectionWorldException ex) {
                logger.debug("PointcutExpression matching rejected target class - trying fallback expression", ex);
                // Actually this is still a "maybe" - treat the pointcut as dynamic if we don't know enough yet
                PointcutExpression fallbackExpression = getFallbackPointcutExpression(targetClass);
                if (fallbackExpression != null) {
                    return fallbackExpression.couldMatchJoinPointsInType(targetClass);
                }
            }
        }
        catch (Throwable ex) {
            logger.debug("PointcutExpression matching rejected target class", ex);
        }
        return false;
    }
}

到此getAdvicesAndAdvisorsForBean方法的调用链就分析的差不多了,回到AbstractAutoProxyCreator类中的wrapIfNecessary方法中。

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
        implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {

    /**
     * Spring实现Bean代理的核心方法。wrapIfNecessary在两处会被调用,一处是getEarlyBeanReference,
     * 另一处是postProcessAfterInitialization
     */
    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        //已经被处理过
        // 1.判断当前bean是否在targetSourcedBeans缓存中存在(已经处理过),如果存在,则直接返回当前bean
        if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
            return bean;
        }
        //不需要被织入逻辑的
        // 2.在advisedBeans缓存中存在,并且value为false,则代表无需处理
        if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
            return bean;
        }
        //是不是基础的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.
        // 返回匹配当前Bean的所有Advice\Advisor\Interceptor
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        // 5.如果存在增强器则创建代理
        if (specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
            //创建Bean对应的代理,SingletonTargetSource用于封装实现类的信息
            // 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;
        }
        //该Bean是不需要进行代理的,下次就不需要重复生成了
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }
}
  • 当执行完getAdvicesAndAdvisorsForBean方法之后,就可以从候选的Advisor列表里筛选出匹配于当前Bean的Advisor列表,获取到Advisor列表之后就会接着执行后续的创建动态代理的步骤了。

  • 由于getAdvicesAndAdvisorsForBean筛选出匹配的Advisor了,将该Bean对应的cacheKey写入到advisedBeans中,并将对应的值设置为true,表示对该Bean进行过Spring AOP的处理了。

  • 之后就会调用createProxy方法去创建目标代理对象实例,创建好动态代理实例之后,就会动态代理实例类型给保存到proxyTypes的缓存里面,并将动态代理实例返回,这样就完成了wrapIfNecessary方法的执行。

  • 如果没有getAdvicesAndAdvisorsForBean没有筛选出匹配的Advisor的话,就证明该Bean不需要织入横切逻辑,此时就会在advisedBeans里给该Bean设置对应的cacheKey和false,以表明该bean是不需要被织入的。

参考:
https://segmentfault.com/a/1190000015830477

https://zhuanlan.zhihu.com/p/104521455

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269