盘点 AOP : AOP 的初始化

1,454 阅读7分钟

这是我参与更文挑战的第17天,活动详情查看: 更文挑战

首先分享之前的所有文章 , 欢迎点赞收藏转发三连下次一定 >>>> 😜😜😜
文章合集 : 🎁 juejin.cn/post/694164…
Github : 👉 github.com/black-ant

当前案例源码 : 👉 Github AOP Source

一 . 前言

之前盘点了 IOC 的相关流程 , 这一篇终于来说一说 AOP 了 , 整个系列会从 :

  • AOP 的初始化
  • AOP 代理类的创建
  • AOP 的拦截
  • AOP 的代理方法调用

以上几个章节分别进行阐述

二 . AOP 的调用入口

Aop 的初始化是指在哪个环节开始 Aop 的配置 :

结合之前 IOC 了解到的 , Aop 的核心还是通过 postProcess 来完成 , 分为 Before 和 After 2个流程

  • applyBeanPostProcessorsBeforeInstantiation (createBean 创建)
  • applyBeanPostProcessorsAfterInitialization (initializeBean 是处理)

// 路线一 : 处理 Aware , 可以通过 getCustomTargetSource 提前生成代理

  • C- AbstractAutowireCapableBeanFactory # createBean
  • C- AbstractAutowireCapableBeanFactory # resolveBeforeInstantiation
  • C- AbstractAutowireCapableBeanFactory # applyBeanPostProcessorsBeforeInstantiation
  • C- AnnotationAwareAspectJAutoProxyCreator # postProcessBeforeInstantiation

// 路线二 : 处理 BeanPostProcessor , 正常代理创建逻辑

  • C- AbstractAutowireCapableBeanFactory # createBean
  • C- AbstractAutowireCapableBeanFactory # doCreateBean
  • C- AbstractAutowireCapableBeanFactory # initializeBean
  • C- AbstractAutowireCapableBeanFactory # applyBeanPostProcessorsAfterInitialization
// Step 1 : 在 createBean 中对 applyBeanPostProcessorsBeforeInstantiation 进行处理
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

    // .... 省略部分逻辑 , 此处初始化代理类
    Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
    
    // 此内将会调用 Step 2 创建逻辑 , 同时处理代理类
    Object beanInstance = doCreateBean(beanName, mbdToUse, args);

    //........
    return beanInstance;

}


// Step 2 : 在 IOC 流程 initializeBean 中 , 会对 PostProcessors 进行处理
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {

    //..........
    invokeInitMethods(beanName, wrappedBean, mbd);

    // 调用 applyBeanPostProcessorsAfterInitialization 处理 AfterPostProcessors
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

    return wrappedBean;
}


处理后 , 在调用bean本身之前将委托给指定的拦截器 , 拦截器分为2种 :

  • common : 为它创建的所有代理共享
  • specific : 每个bean实例唯一

代理的限制 : 子类可以应用任何策略来决定一个bean是否要被代理,例如根据类型、名称、定义细节等

为什么有 getCustomTargetSource 提前生成 ?

getCustomTargetSource 是通过 TargetSourceCreator 对象 ,在 Bean 实例化之前 , 为其生成代理对象 .

该模式需要自行定制 , 详见 附录 : 创建 customTargetSource

2.1 applyBeanPostProcessorsBeforeInstantiation

Step 1 : 调用 PostProcessorsBefore C- AbstractAutowireCapableBeanFactory

此处主要会调用 org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator 进行处理

for (BeanPostProcessor bp : getBeanPostProcessors()) {
    if (bp instanceof InstantiationAwareBeanPostProcessor) {
         // idp -> org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
        Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
         //..........
    }
}

Step 2 : 配置前置条件 C- AbstractAutoProxyCreator

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;
        }
        // isInfrastructureClass -> 不应该被代理的基础结构类
         // shouldSkip -> 注意 , 子类重写 shouldSkip , 用于跳过自动代理
        if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
             // PRO21001 -> advisedBeans 的作用
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return null;
        }
    }

    // 如果有一个自定义的TargetSource,那么在这里创建代理
    // TargetSource将以自定义的方式处理目标实例
    TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
    if (targetSource != null) {
        // 自行定制 CustomTargetSource 逻辑后 , 即会在此处创建代理
        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;
}


Step 2-1 : 返回目标实例


C- getCustomTargetSource : 为bean实例创建目标源。如果设置,使用任何TargetSourceCreators
protected TargetSource getCustomTargetSource(Class<?> beanClass, String beanName) {
    // 此处要求存在创建者,  需要在执行定制
    if (this.customTargetSourceCreators != null &&
        this.beanFactory != null && this.beanFactory.containsBean(beanName)) {
        for (TargetSourceCreator tsc : this.customTargetSourceCreators) {
            // 通过创建者回去目标对象代理类
            TargetSource ts = tsc.getTargetSource(beanClass, beanName);
            if (ts != null) {
                return ts;
            }
        }
    }

    // 未定义 customTargetSource 会在此处直接返回
    return null;
}

2.2 applyBeanPostProcessorsAfterInitialization

前面说的是在 Bean 实例化之前创建代理 ,但是通常情况下 , 是在 Bean 实例化之后进行代理逻辑的创建

Step 1 : IOC initializeBean 入口

IOC initializeBean 时 , 调用 applyBeanPostProcessorsAfterInitialization 逻辑

if (mbd == null || !mbd.isSynthetic()) {
    wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}

Step 2 : applyBeanPostProcessorsAfterInitialization 中循环 BeanPostProcessor 进行处理

for (BeanPostProcessor processor : getBeanPostProcessors()) {
    // BeanPostProcessor -> org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
    Object current = processor.postProcessAfterInitialization(result, beanName);
    //........ 
}

PS : 可以看到 , 这里拿到的Bean 的 PostProcessor 就是 AnnotationAwareAspectJAutoProxyCreator

Step 3 : AbstractAutoProxyCreator # postProcessAfterInitialization 构建代理对象

如果bean被标识为代理,则使用配置的拦截器创建代理

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
         // cacheKey 用来标识
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (this.earlyProxyReferences.remove(cacheKey) != bean) {
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

Step 4 : wrapIfNecessary 正式创建代理类 C- AbstractAutoProxyCreator


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

    // 如果配置了通知 ,则创建Proxy 代理
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
         // 核心逻辑 , 创建代理 -> 2.2 Aop 代理类的创建
         // 可以看到 , 这里构建了一个 SingletonTargetSource -> PRO21002 : TargetSource 是什么 ?
        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;
}

PRO21001 -> advisedBeans 的作用

// advisedBeans 用于标识当前 Bean 的代理状态 , 该对象 key 为 getCacheKey 获取
Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<>(256);

- 如果无需代理 -> advisedBeans.put(cacheKey, Boolean.FALSE)
- 如果已经代理 -> advisedBeans.put(cacheKey, Boolean.TRUE)
- 最终无操作(没用注解标注) -> advisedBeans.put(cacheKey, Boolean.FALSE)

PRO21002 : TargetSource 是什么 ?

可以看到 , 这里实际上和下面的 applyBeanPostProcessorsAfterInitialization 类似 , 那么上面是处理什么?

TargetSource用于获取AOP调用的当前"目标" , 在Spring代理目标bean的时候,其并不是直接创建一个目标bean的对象实例的,而是通过一个TargetSource类型的对象将目标bean进行封装 , 然后通过 getTarget 获取目标对象

TargetSource 是一个接口 , 可以通过下图看到其本身的体系结构 :

TargetSource-system.png

三 . 补充点 : Advisors 详解之 getAdvicesAndAdvisorsForBean 流程

此部分对 getAdvicesAndAdvisorsForBean 的流程进行详细的浏览

Step 1 : 筛选 Advices C- AbstractAutoProxyCreator

M- getAdvicesAndAdvisorsForBean
Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName,TargetSource customTargetSource)
    ?- 返回给定的bean是否要被代理,要应用哪些附加通知(例如AOP Alliance拦截器)和建议器
    
// 该类主要有2个实现类 : AbstractAdvisorAutoProxyCreator , BeanNameAutoProxyCreator
    
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();
}

Step 2 : 为自动代理这个类找到所有符合条件的advisor

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    // Step 2-1 : 查询切面对应的所有的通知
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    // Step 2-2 : 筛选与类对应的织入切点
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    // 空对象, 待实现
    extendAdvisors(eligibleAdvisors);
    if (!eligibleAdvisors.isEmpty()) {
        eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    return eligibleAdvisors;
}

Step 2-1 : BeanFactoryAdvisorRetrievalHelper 获取通知对象

2-1-1 : 先调用具体实现类 (AnnotationAwareAspectJAutoProxyCreator)

👉该过程中对切面进行了扫描 ,并且缓存了所有的通知点

protected List<Advisor> findCandidateAdvisors() {
    // 根据超类规则添加所有找到的Spring 通知
    List<Advisor> advisors = super.findCandidateAdvisors();
    // 为bean工厂中的所有AspectJ方面构建 通知
    if (this.aspectJAdvisorsBuilder != null) {
         // 2-1-1-1
        advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    }
    return advisors;
}

// 2-1-1-1  : 构建通知者
public List<Advisor> buildAspectJAdvisors() {
    List<String> aspectNames = this.aspectBeanNames;

    if (aspectNames == null) {
        synchronized (this) {
            aspectNames = this.aspectBeanNames;
            if (aspectNames == null) {
                List<Advisor> advisors = new ArrayList<>();
                aspectNames = new ArrayList<>();
                String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                            this.beanFactory, Object.class, true, false);
                for (String beanName : beanNames) {
                    if (!isEligibleBean(beanName)) {
                        continue;
                    }
                    // 需要在实例化缓存之前被处理
                    Class<?> beanType = this.beanFactory.getType(beanName);
                    if (beanType == null) {
                        continue;
                    }
                    // 过滤出切面 Bean  , debug 过程中会拿到我自己定义的切面
                    if (this.advisorFactory.isAspect(beanType)) {
                        aspectNames.add(beanName);
                        // 获取切面元数据 -> PIC0001
                        AspectMetadata amd = new AspectMetadata(beanType, beanName);
                        if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                            // AspectInstanceFactory的子接口,它返回与aspectj注释类关联的AspectMetadata
                            MetadataAwareAspectInstanceFactory factory =
                                        new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
                            // 获得所有得通知点 -> PIC0002
                            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();
    }
    
    // 循环 aspect 切面 , 添加通知
    List<Advisor> advisors = new ArrayList<>();
    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;
}


PIC0001 : 切面元数据

image.png

PIC0002 : 待通知的切点 image.png

2-1-2 : 调用父类

protected List<Advisor> findCandidateAdvisors() {
    return this.advisorRetrievalHelper.findAdvisorBeans();
}

2-1-3 : 实际方法

public List<Advisor> findAdvisorBeans() {
    // 确定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!
        advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                    this.beanFactory, Advisor.class, true, false);
        this.cachedAdvisorBeanNames = advisorNames;
    }
    if (advisorNames.length == 0) {
        return new ArrayList<>();
    }

    List<Advisor> advisors = new ArrayList<>();
    for (String name : advisorNames) {
        if (isEligibleBean(name)) {
            if (this.beanFactory.isCurrentlyInCreation(name)) {
                // log 省略
            } 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)) {
                            // 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;
}

Step 2-2 : 搜索给定的候选advisor以找到适用于指定bean的所有advisor


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

    ProxyCreationContext.setCurrentProxiedBeanName(beanName);
    try {
        return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
    } finally {
        ProxyCreationContext.setCurrentProxiedBeanName(null);
    }
}


Step 2-3 : sort 排序

protected List<Advisor> sortAdvisors(List<Advisor> advisors) {
    AnnotationAwareOrderComparator.sort(advisors);
    return advisors;
}

// [Pro] : AnnotationAwareOrderComparator 是什么 ?
AnnotationAwareOrderComparator是OrderComparator的扩展,它支持Spring的Ordered接口以及Order和Priority注释

总结

AOP 初始化阶段基本上就完成了 , 后续再来看一下代理类的创建 . 来总结一下这篇文档得所有概念 :

  • 由 initializeBean 开启 AOP 的主处理逻辑
  • AbstractAutowireCapableBeanFactory 调用 applyBeanPostProcessorsBeforeInstantiation 创建自定义代理类
  • AbstractAutowireCapableBeanFactory 调用 applyBeanPostProcessorsAfterInitialization 筛选通知器

附录 : 创建 customTargetSource

参考地址 (原文这一块写的更加详细) @ blog.csdn.net/qq_39002724…

Step 1 :准备 CustomTargetSource

public class DefaultCustomTargetSource extends AbstractBeanFactoryBasedTargetSource {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Override
    public Object getTarget() throws Exception {
        logger.info("------> 进入 [DefaultCustomTargetSource] , 返回当前目标对象 <-------");
        return getBeanFactory().getBean(getTargetBeanName());
    }
}

Step 2 : 准备创建者

该对象用于返回创建的 CustomTargetSource

public class DefaultCustomerTargetSourceCreator extends AbstractBeanFactoryBasedTargetSourceCreator {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Override
    protected AbstractBeanFactoryBasedTargetSource createBeanFactoryBasedTargetSource(Class<?> beanClass, String beanName) {
        logger.info("------> CustomerTargetSourceCreator build : [进入流程创建过程 , 返回默认资源类 DefaultCustomTargetSource] <-------");
        if (getBeanFactory() instanceof ConfigurableListableBeanFactory) {
            if (beanClass.isAssignableFrom(OtherService.class)) {
                return new DefaultCustomTargetSource();
            }
        }
        return null;
    }
}

Step 3 : CustomTargetSource 资源配置

@Component
public class CustomTargetSourceCreatorConfig implements BeanPostProcessor, PriorityOrdered, BeanFactoryAware {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    private BeanFactory beanFactory;

    @Override
    public int getOrder() {
        return 45;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        logger.info("------> 进入 CustomTargetSourceCreatorConfig 初始化加载逻辑 , 返回默认创建者  <-------");
        if (bean instanceof AnnotationAwareAspectJAutoProxyCreator) {
            AnnotationAwareAspectJAutoProxyCreator annotationAwareAspectJAutoProxyCreator = (AnnotationAwareAspectJAutoProxyCreator) bean;
            DefaultCustomerTargetSourceCreator customTargetSourceCreator = new DefaultCustomerTargetSourceCreator();
            customTargetSourceCreator.setBeanFactory(beanFactory);
            annotationAwareAspectJAutoProxyCreator.setCustomTargetSourceCreators(customTargetSourceCreator);
        }
        return bean;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }
}