【Spring注解驱动开发】AOP核心类源码解析,这是最全的一篇了!!

简介: 昨天二狗子让我给他讲@EnableAspectJAutoProxy注解,讲到AnnotationAwareAspectJAutoProxyCreator类的源码时,二狗子消化不了了。这不,今天又来让我给他讲讲AOP的核心类。那我们就开始吧!

类结构图

我们先来看下AnnotationAwareAspectJAutoProxyCreator类的结构图。

微信图片_20211119153658.jpg

上图中一些 类/接口 的介绍:

AspectJAwareAdvisorAutoProxyCreator : 公开了AspectJ的调用上下文,并弄清楚来自同一切面的多个Advisor在AspectJ中的优先级规则。

AbstractAdvisorAutoProxyCreator : 通用自动代理创建器,它基于检测到的每个顾问程序为特定bean构建AOP代理。

AbstractAutoProxyCreator : 扩展了  ProxyProcessorSupport,实现了SmartInstantiationAwareBeanPostProcessor、BeanFactoryAware 接口,是BeanPostProcessor 实现,该实现使用AOP代理包装每个合格的bean,并在调用bean本身之前委派给指定的拦截器。

BeanFactoryAware : 实现了该接口的Bean可以知道它属于那个 BeanFactory,Bean可以通过Spring容器查找它的协同者(依赖查找),但大多数的Bean是通过构造器参数和Bean方法(依赖注入)来获取它的协同者。

BeanPostProcessor :工厂钩子,允许自定义修改新的bean实例。例如,检查标记接口或使用代理包装bean。如果我们需要在Spring容器中完成Bean的实例化,配置和其初始化前后添加一些自己的逻辑处理,我们就可以定义一个或多个BeanPostProcessor接口的实现,然后注册到容器中。

InstantiationAwareBeanPostProcessor : BeanPostProcessor  的子接口,它添加了实例化之前的回调,以及实例化之后但设置了显式属性或自动装配之前的回调。它内部提供了3个方法,再加上BeanPostProcessor接口内部的2个方法,实现这个接口需要实现5个方法。InstantiationAwareBeanPostProcessor 接口的主要作用在于目标对象的实例化过程中需要处理的事情,包括实例化对象的前后过程以及实例的属性设置。

SmartInstantiationAwareBeanPostProcessor : InstantiationAwareBeanPostProcessor 接口的扩展,多出了3个方法,添加了用于预测已处理bean的最终类型的回调,再加上父接口的5个方法,所以实现这个接口需要实现8个方法,主要作用也是在于目标对象的实例化过程中需要处理的事情。

总之: AspectJAwareAdvisorAutoProxyCreator为 AspectJ 切面类创建自动代理。

核心类解析

BeanPostProcessor 接口中的两个方法 postProcessBeforeInitialization 和 postProcessAfterInitialization,作用是对Bean初始化前后添加一些自己的逻辑。

@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    return bean;
}

InstantiationAwareBeanPostProcessorBeanPostProcessor 的子接口,它额外增加了3个新的方法:postProcessBeforeInstantiation( 目标对象被实例化之前调用的方法,可以返回目标实例的一个代理用来代替目标实例 )、postProcessAfterInstantiation(该方法在Bean实例化之后执行,返回false,会忽略属性值的设置;如果返回true,会按照正常流程设置属性值) 和 postProcessPropertyValues(对属性值进行修改,未来版本将会删除)

@Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
    return null;
}
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
    return true;
}
@Nullable
default PropertyValues postProcessPropertyValues(
    PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
    return pvs;
}

SmartInstantiationAwareBeanPostProcessor接口继承InstantiationAwareBeanPostProcessor接口,里面定义了3个方法:predictBeanType(预测Bean的类型)、determineCandidateConstructors(选择合适的构造器)、getEarlyBeanReference(解决循环引用问题)。

@Nullable
default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
    return null;
}
@Nullable
default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
    return null;
}
default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
    return bean;
}

AbstractAutoProxyCreator 是AOP的一个核心类,它实现了SmartInstantiationAwareBeanPostProcessor、BeanFactoryAware 接口,实现了代理创建的逻辑,使用AOP代理包装每个合格的bean,并在调用bean本身之前委派给指定的拦截器。

AbstractAdvisorAutoProxyCreator 通用自动代理创建器,它基于检测每个bean的增强器,为特殊的bean构建AOP代理。子类可以重写此findCandidateAdvisors()方法,以返回适用于任何对象的advisor的自定义列表,子类还可以重写继承的AbstractAutoProxyCreator.shouldSkip()方法,以将某些对象排除在自动代理之外。

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

AspectJAwareAdvisorAutoProxyCreator 扩展 AbstractAdvisorAutoProxyCreator,公开了AspectJ的调用上下文,并在多个增强器来自同一切面时搞清楚AspectJ的建议优先级顺序。按AspectJ优先级排序其余部分:

@Override
@SuppressWarnings("unchecked")
protected List<Advisor> sortAdvisors(List<Advisor> advisors) {
    List<PartiallyComparableAdvisorHolder> partiallyComparableAdvisors = new ArrayList<>(advisors.size());
    for (Advisor element : advisors) {
        partiallyComparableAdvisors.add(
            new PartiallyComparableAdvisorHolder(element, DEFAULT_PRECEDENCE_COMPARATOR));
    }
    List<PartiallyComparableAdvisorHolder> sorted = PartialOrder.sort(partiallyComparableAdvisors);
    if (sorted != null) {
        List<Advisor> result = new ArrayList<>(advisors.size());
        for (PartiallyComparableAdvisorHolder pcAdvisor : sorted) {
            result.add(pcAdvisor.getAdvisor());
        }
        return result;
    }
    else {
        return super.sortAdvisors(advisors);
    }
}

在增强链头部增加一个ExposeInvocationInterceptor,使用AspectJ表达式切入点和使用AspectJ样式的advisor时,需要这些附加advisor。

protected void extendAdvisors(List<Advisor> candidateAdvisors) {
      AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
}

如果此后处理器不应该考虑将给定的bean用于自动代理,子类应重写此方法以返回true

@Override
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
    // TODO: Consider optimization by caching the list of the aspect names
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    for (Advisor advisor : candidateAdvisors) {
        if (advisor instanceof AspectJPointcutAdvisor &&
            ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
            return true;
        }
    }
    return super.shouldSkip(beanClass, beanName);
}

AspectJAwareAdvisorAutoProxyCreator 还有一个子类叫 AnnotationAwareAspectJAutoProxyCreator,子类AnnotationAwareAspectJAutoProxyCreator是用于处理当前应用程序上下文中的所有AspectJ注释方面以及Spring Advisor。如果Spring  AOP的基于代理的模型能够应用任何AspectJ注释的类,它们的advisor将被自动识别,这涵盖了方法执行连接点,Spring  Advisor的处理遵循AbstractAdvisorAutoProxyCreator中建立的规则。

生成代理对象

从使用aop:xxx标签来自动生成代理的话,先看看AopNamespaceHandler,使用aop:config标签则使用 ConfigBeanDefinitionParser 解析,使用了aop:aspectj-autoproxy标签则使用 AspectJAutoProxyBeanDefinitionParser 解析,依次类推。

@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());
}
  • aop:config方式使用 AspectJAwareAdvisorAutoProxyCreator 创建代理
  • aop:aspectj-autoproxy使用 AnnotationAwareAspectJAutoProxyCreator 创建代理

ConfigBeanDefinitionParser.java

@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
    CompositeComponentDefinition compositeDef =
        new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
    parserContext.pushContainingComponent(compositeDef);
    configureAutoProxyCreator(parserContext, element); // 注册AspectJAwareAdvisorAutoProxyCreator
    List<Element> childElts = DomUtils.getChildElements(element);
    for (Element elt: childElts) {
        String localName = parserContext.getDelegate().getLocalName(elt);
        if (POINTCUT.equals(localName)) {
            parsePointcut(elt, parserContext);
        }
        else if (ADVISOR.equals(localName)) {
            parseAdvisor(elt, parserContext);
        }
        else if (ASPECT.equals(localName)) {
            parseAspect(elt, parserContext);
        }
    }
    parserContext.popAndRegisterContainingComponent();
    return null;
}
private void configureAutoProxyCreator(ParserContext parserContext, Element element) {
    AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext, element);
}

AopConfigUtils.java

@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
    CompositeComponentDefinition compositeDef =
        new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
    parserContext.pushContainingComponent(compositeDef);
    configureAutoProxyCreator(parserContext, element); // 注册AspectJAwareAdvisorAutoProxyCreator
    List<Element> childElts = DomUtils.getChildElements(element);
    for (Element elt: childElts) {
        String localName = parserContext.getDelegate().getLocalName(elt);
        if (POINTCUT.equals(localName)) {
            parsePointcut(elt, parserContext);
        }
        else if (ADVISOR.equals(localName)) {
            parseAdvisor(elt, parserContext);
        }
        else if (ASPECT.equals(localName)) {
            parseAspect(elt, parserContext);
        }
    }
    parserContext.popAndRegisterContainingComponent();
    return null;
}
private void configureAutoProxyCreator(ParserContext parserContext, Element element) {
    AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext, element);
}

AopConfigUtils.java

public static void registerAspectJAutoProxyCreatorIfNecessary(
    ParserContext parserContext, Element sourceElement) {
    // 在这里注册的是AspectJAwareAdvisorAutoProxyCreator
    BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary(
        parserContext.getRegistry(), parserContext.extractSource(sourceElement));
    useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
    registerComponentIfNecessary(beanDefinition, parserContext); // 注册组件
}
@Nullable
public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(
    BeanDefinitionRegistry registry, @Nullable Object source) {
    return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source);
}

AspectJAwareAdvisorAutoProxyCreator 实现了 BeanPostProcessor 等上面介绍的接口,主要作用于Bean初始化前后,实例化前后,所有的Bean都被作用到。InstantiationAwareBeanPostProcessorBeanPostProcessor的子接口,但它的调用时间点发生在Bean实例化前,在真正调用doCreateBean()创建bean实例之前执行postProcessBeforeInstantiation()。

AbstractAutoProxyCreator.java

@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
    Object cacheKey = getCacheKey(beanClass, beanName);  // 得到一个缓存的唯一key(根据beanClass和beanName生成唯一key)
    // 如果当前targetSourcedBeans(通过自定义TargetSourceCreator创建的TargetSource)不包含cacheKey
    if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
        if (this.advisedBeans.containsKey(cacheKey)) {  //advisedBeans(已经被增强的Bean,即AOP代理对象)中包含当前cacheKey,返回null,即走Spring默认流程
            return null;
        }
        if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {// 如果是基础设施类(如Advisor、Advice、AopInfrastructureBean的实现)不进行处理;(略)
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return null;
        }
    }
    // 如果有自定义的TargetSource,在此处创建代理
    // 禁止目标Bean的不必要的默认实例化:
    // TargetSource将以自定义方式处理目标实例。
    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;
}

通过 AbstractAutoProxyCreator 中的 postProcessAfterInitialization() 创建AOP代理。

@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (!this.earlyProxyReferences.contains(cacheKey)) {  // 如果之前调用过getEarlyBeanReference获取包装目标对象到AOP代理对象(如果需要),则不再执行
            return wrapIfNecessary(bean, beanName, cacheKey);  // 包装目标对象到AOP代理对象(如果需要)
        }
    }
    return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { // 通过TargetSourceCreator进行自定义TargetSource不需要包装
        return bean;
    }
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {  // 不应该被增强对象不需要包装
        return bean;
    }
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { // 基础设施或应该skip的不需要保证
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }
    // 如果有advise则创建代理。
    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;
}
相关文章
|
Java 开发者
重学Java基础篇—Java类加载顺序深度解析
本文全面解析Java类的生命周期与加载顺序,涵盖从加载到卸载的七个阶段,并深入探讨初始化阶段的执行规则。通过单类、继承体系的实例分析,明确静态与实例初始化的顺序。同时,列举六种触发初始化的场景及特殊场景处理(如接口初始化)。提供类加载完整流程图与记忆口诀,助于理解复杂初始化逻辑。此外,针对空指针异常等问题提出排查方案,并给出最佳实践建议,帮助开发者优化程序设计、定位BUG及理解框架机制。最后扩展讲解类加载器层次与双亲委派机制,为深入研究奠定基础。
523 0
|
9月前
|
设计模式 Java 开发者
如何快速上手【Spring AOP】?从动态代理到源码剖析(下篇)
Spring AOP的实现本质上依赖于代理模式这一经典设计模式。代理模式通过引入代理对象作为目标对象的中间层,实现了对目标对象访问的控制与增强,其核心价值在于解耦核心业务逻辑与横切关注点。在框架设计中,这种模式广泛用于实现功能扩展(如远程调用、延迟加载)、行为拦截(如权限校验、异常处理)等场景,为系统提供了更高的灵活性和可维护性。
1329 0
|
人工智能 API 开发者
HarmonyOS Next~鸿蒙应用框架开发实战:Ability Kit与Accessibility Kit深度解析
本书深入解析HarmonyOS应用框架开发,聚焦Ability Kit与Accessibility Kit两大核心组件。Ability Kit通过FA/PA双引擎架构实现跨设备协同,支持分布式能力开发;Accessibility Kit提供无障碍服务构建方案,优化用户体验。内容涵盖设计理念、实践案例、调试优化及未来演进方向,助力开发者打造高效、包容的分布式应用,体现HarmonyOS生态价值。
873 27
|
安全 API
鸿蒙开发:实现AOP代码插桩能力
正确的运用AOP,可以提升代码的模块化、复用性、可维护性和灵活性,同时降低了耦合度,使系统更易于扩展和维护。
322 13
鸿蒙开发:实现AOP代码插桩能力
|
人工智能 小程序 前端开发
【一步步开发AI运动小程序】十九、运动识别中如何解析RGBA帧图片?
本文介绍了如何将相机抽取的RGBA帧图像解析为`.jpg`或`.png`格式,适用于体测、赛事等场景。首先讲解了RGBA图像结构,其为一维数组,每四个元素表示一个像素的颜色与透明度值。接着通过`uni.createOffscreenCanvas()`创建离屏画布以减少绘制干扰,并提供代码实现,将RGBA数据逐像素绘制到画布上生成图片。最后说明了为何不直接使用拍照API及图像转换的调用频率建议,强调应先暂存帧数据,运动结束后再进行转换和上传,以优化性能。
|
存储 监控 安全
重学Java基础篇—类的生命周期深度解析
本文全面解析了Java类的生命周期,涵盖加载、验证、准备、解析、初始化、使用及卸载七个关键阶段。通过分阶段执行机制详解(如加载阶段的触发条件与技术实现),结合方法调用机制、内存回收保护等使用阶段特性,以及卸载条件和特殊场景处理,帮助开发者深入理解JVM运作原理。同时,文章探讨了性能优化建议、典型异常处理及新一代JVM特性(如元空间与模块化系统)。总结中强调安全优先、延迟加载与动态扩展的设计思想,并提供开发建议与进阶方向,助力解决性能调优、内存泄漏排查及框架设计等问题。
620 5
|
安全 IDE Java
重学Java基础篇—Java Object类常用方法深度解析
Java中,Object类作为所有类的超类,提供了多个核心方法以支持对象的基本行为。其中,`toString()`用于对象的字符串表示,重写时应包含关键信息;`equals()`与`hashCode()`需成对重写,确保对象等价判断的一致性;`getClass()`用于运行时类型识别;`clone()`实现对象复制,需区分浅拷贝与深拷贝;`wait()/notify()`支持线程协作。此外,`finalize()`已过时,建议使用更安全的资源管理方式。合理运用这些方法,并遵循最佳实践,可提升代码质量与健壮性。
486 1
|
数据可视化 测试技术 API
前后端分离开发:如何高效调试API?有工具 vs 无工具全解析
在前后端分离的开发模式中,API 调试的效率直接影响项目的质量和交付速度。通过本文的对比分析,我们可以看到无工具调试模式虽具备灵活性和代码复用能力,但在操作便利性和团队协作上稍显不足。而传统的外部调试工具带来了可视化、高效协作与扩展性,却可能存在工具切换带来的开发链路断层问题。Apipost-Hepler 融合了两者的优势,让开发者无需离开熟悉的 IDEA 环境,就能享受可视化调试工具的强大功能。
494 5
|
移动开发 前端开发 JavaScript
从入门到精通:H5游戏源码开发技术全解析与未来趋势洞察
H5游戏凭借其跨平台、易传播和开发成本低的优势,近年来发展迅猛。接下来,让我们深入了解 H5 游戏源码开发的技术教程以及未来的发展趋势。

热门文章

最新文章

推荐镜像

更多
  • DNS