Spring boot 中 AOP 相关的 BeanPostProcessor

这篇介绍了BeanPostProcessor的注册,这篇介绍了BeanPostProcessor 的调用,接下来看一下Spring boot 中 AOP 相关的基础 BeanPostProcessor


一、自动配置

注册基础的BeanDefinition

  • 模块:spring-boot-autoconfigure
  • 基础包:org.springframework.boot.autoconfigure
  • AOP相关的包:org.springframework.boot.autoconfigure.aop

二、AopAutoConfiguration

1.源码

/**
 * AopAutoConfiguration 是 Spring Boot 自动配置的一部分,用于启用 Spring AOP 支持。
 * 等价于在配置中手动添加 @EnableAspectJAutoProxy 注解。
 *
 * <p>如果配置项 spring.aop.auto=false,则不会激活此自动配置。</p>
 * <p>默认情况下,会使用基于类的代理(proxyTargetClass = true),
 * 但可以通过设置 spring.aop.proxy-target-class=false 来覆盖这一行为。</p>
 *
 * @author Dave Syer
 * @author Josh Long
 * @since 1.0.0
 * @see EnableAspectJAutoProxy
 */

// 启用 Spring Boot 的自动配置机制
@AutoConfiguration
// 条件注解:只有当配置属性 spring.aop.auto 为 true(或不存在时,默认匹配)才会加载该配置
@ConditionalOnBooleanProperty(name = "spring.aop.auto", matchIfMissing = true)
public class AopAutoConfiguration {

    /**
     * 当类路径下存在 org.aspectj.weaver.Advice 时,
     * 表示项目引入了 AspectJ 类库,将启用基于 AspectJ 的 AOP 自动代理配置。
     */
    @Configuration(proxyBeanMethods = false)
    @ConditionalOnClass(Advice.class)
    static class AspectJAutoProxyingConfiguration {

        /**
         * 当配置项 spring.aop.proxy-target-class=false 时,
         * 使用 JDK 动态代理来创建代理对象。
         */
        @Configuration(proxyBeanMethods = false)
        @EnableAspectJAutoProxy(proxyTargetClass = false)
        @ConditionalOnBooleanProperty(name = "spring.aop.proxy-target-class", havingValue = false)
        static class JdkDynamicAutoProxyConfiguration {

        }

        /**
         * 当配置项 spring.aop.proxy-target-class=true 或未配置时(matchIfMissing = true),
         * 使用 CGLIB 代理来创建代理对象(基于类的代理)。
         */
        @Configuration(proxyBeanMethods = false)
        @EnableAspectJAutoProxy(proxyTargetClass = true)
        @ConditionalOnBooleanProperty(name = "spring.aop.proxy-target-class", matchIfMissing = true)
        static class CglibAutoProxyConfiguration {

        }

    }

    /**
     * 如果类路径下没有 org.aspectj.weaver.Advice 类(即未引入 AspectJ),
     * 并且配置项 spring.aop.proxy-target-class 为 true 或未配置,
     * 则进入此配置类,强制使用基于类的代理方式。
     */
    @Configuration(proxyBeanMethods = false)
    @ConditionalOnMissingClass("org.aspectj.weaver.Advice")
    @ConditionalOnBooleanProperty(name = "spring.aop.proxy-target-class", matchIfMissing = true)
    static class ClassProxyingConfiguration {

        /**
         * 定义一个静态 Bean,类型为 BeanFactoryPostProcessor,
         * 强制 Spring 使用基于类的代理方式(即使目标类没有实现接口)。
         */
        @Bean
        static BeanFactoryPostProcessor forceAutoProxyCreatorToUseClassProxying() {
            return (beanFactory) -> {
                if (beanFactory instanceof BeanDefinitionRegistry registry) {
                    // 注册自动代理创建者(如果尚未注册)
                    AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
                    // 强制使用基于类的代理
                    AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
                }
            };
        }

    }

}

说明:

  • AopAutoConfiguration 是 Spring Boot 中用于自动配置 AOP 的核心类。
  • 满足条件@ConditionalOnClass(Advice.class),根据配置参数 spring.aop.proxy-target-class 决定使用 JDK 动态代理 还是 CGLIB 代理
  • 满足条件@ConditionalOnMissingClass("org.aspectj.weaver.Advice"),Spring 会通过自定义一个 BeanFactoryPostProcessor 注册自动代理创建者。

三、@EnableAspectJAutoProxy

1.源码

/**
 * <b>注意</b>:{@code @EnableAspectJAutoProxy} 只对其所在的应用上下文(ApplicationContext)生效,
 * 这样可以让你在不同层级选择性地启用代理功能。如果你希望在整个应用的不同层级都启用该功能,
 * 比如根 Web 应用上下文(root web application context)和多个独立的 {@code DispatcherServlet}
 * 所属的子上下文(child contexts),你需要在每个上下文中单独声明此注解。
 *
 * <p>使用这个功能要求类路径中包含 {@code aspectjweaver} 依赖。
 * 虽然对于整个 {@code spring-aop} 来说,这个依赖是可选的,
 * 但对于 {@code @EnableAspectJAutoProxy} 注解及其底层机制来说,它是必须的。
 *
 * @author Chris Beams
 * @author Juergen Hoeller
 * @since 3.1
 * @see org.aspectj.lang.annotation.Aspect
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class) // 导入配置类,用于注册 AOP 相关组件
public @interface EnableAspectJAutoProxy {

	/**
	 * 设置是否创建基于子类(CGLIB)的代理对象,而不是默认的基于接口的 JDK 动态代理。
	 * 默认值为 false,表示优先使用 JDK 动态代理。
	 */
	boolean proxyTargetClass() default false;

	/**
	 * 设置是否将生成的代理对象暴露给 AOP 框架,以便通过
	 * {@link org.springframework.aop.framework.AopContext} 类进行访问。
	 * 默认关闭,即不能保证可以通过 AopContext 获取当前代理对象。
	 * 
	 * @since 4.3.1
	 */
	boolean exposeProxy() default false;
}

📌 说明

内容说明
作用启用对 @Aspect 注解切面的支持,等价于 XML 配置中的 <aop:aspectj-autoproxy/>
核心注解@Import(AspectJAutoProxyRegistrar.class),导入自动代理创建逻辑
proxyTargetClass控制使用 CGLIB 代理(true)还是 JDK 动态代理(false,默认)
exposeProxy控制是否将代理对象暴露给 ThreadLocal,方便在 Advice 中通过 AopContext.currentProxy() 获取
注意事项必须引入 aspectjweaver 依赖才能支持注解风格的切面
使用方式通常与 @Configuration 配合使用,在 Java 配置类上标注

2.AspectJAutoProxyRegistrar

/**
 * 根据给定的 @{@link EnableAspectJAutoProxy} 注解配置,
 * 在当前的 {@link BeanDefinitionRegistry} 中注册一个
 * {@link org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator}
 * 实例。
 *
 * <p>该类用于支持基于注解风格的 AOP 自动代理创建器(AnnotationAwareAspectJAutoProxyCreator),
 * 通常由 @{@link EnableAspectJAutoProxy} 注解导入使用。
 *
 * @author Chris Beams
 * @author Juergen Hoeller
 * @since 3.1
 * @see EnableAspectJAutoProxy
 */
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

	/**
	 * 根据导入该注册器的 @{@link Configuration} 类上定义的
	 * @{@link EnableAspectJAutoProxy#proxyTargetClass()} 属性值,
	 * 来注册、升级并配置 AspectJ 自动代理创建器。
	 *
	 * <p>主要完成以下工作:
	 * 1. 注册 AnnotationAwareAspectJAutoProxyCreator(如果尚未注册)
	 * 2. 如果启用了 proxyTargetClass = true,则强制使用 CGLIB 代理
	 * 3. 如果启用了 exposeProxy = true,则将代理对象暴露给 ThreadLocal 上下文
	 *
	 * @param importingClassMetadata 导入该注册器的类的注解元数据
	 * @param registry               BeanDefinition 注册表,用于注册自动代理创建器
	 */
	@Override
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

		// 注册或升级为支持 @Aspect 注解切面的自动代理创建器
		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

		// 获取 @EnableAspectJAutoProxy 注解上的属性值
		AnnotationAttributes enableAspectJAutoProxy =
				AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
		
		// 如果存在该注解,则根据其属性进一步配置自动代理行为
		if (enableAspectJAutoProxy != null) {
			
			// 如果设置了 proxyTargetClass = true,则强制使用 CGLIB 子类代理
			if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
				AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
			}
			
			// 如果设置了 exposeProxy = true,则将代理对象暴露给 ThreadLocal 上下文
			if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
				AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
			}
		}
	}

📌 说明

内容描述
作用用于在 Spring 容器中注册和配置 AnnotationAwareAspectJAutoProxyCreator
触发方式@EnableAspectJAutoProxy 注解通过 @Import 引入
核心逻辑- 注册 AOP 自动代理创建器
- 支持 proxyTargetClass 配置
- 支持 exposeProxy 配置
相关类- @EnableAspectJAutoProxy
- AopConfigUtils
- AnnotationAwareAspectJAutoProxyCreator

四、AopConfigUtils

1.源码

/**
 * AOP 自动代理创建器(AutoProxyCreator)的注册工具类。
 *
 * <p>Spring AOP 中存在多个不同能力的 AutoProxyCreator 实现类:
 * - InfrastructureAdvisorAutoProxyCreator:最基础,仅处理 ROLE_INFRASTRUCTURE 的 Advisor
 * - AspectJAwareAdvisorAutoProxyCreator:支持 AspectJ 表达式和规则
 * - AnnotationAwareAspectJAutoProxyCreator:功能最强大,支持 @Aspect 注解风格切面
 *
 * 该工具类提供一个“升级协议”,确保当你请求注册某个 AutoProxyCreator 时,
 * 如果已经存在其他实现,则会根据优先级决定是否替换为更高级别的版本。
 *
 * @author Rob Harrop
 * @author Juergen Hoeller
 * @author Mark Fisher
 * @since 2.5
 */
public abstract class AopConfigUtils {

	/**
	 * Spring 内部管理的自动代理创建器 Bean 的名称。
	 * 这个 Bean 是 Spring 容器中负责生成 AOP 代理的核心组件。
	 */
	public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
			"org.springframework.aop.config.internalAutoProxyCreator";

	/**
	 * 存储不同 AutoProxyCreator 类的优先级顺序。
	 * 列表越靠后的类,功能越强,优先级越高。
	 */
	private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>(3);

	static {
		// 初始化优先级排序:
		APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);      // 最基础
		APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);        // 支持 AspectJ 表达式
		APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);     // 支持 @Aspect 注解切面
	}

	/**
	 * 必要时注册最基础的 AutoProxyCreator。
	 * 若容器中已有更高优先级的 AutoProxyCreator,则不会重复注册。
	 */
	public static @Nullable BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
		return registerAutoProxyCreatorIfNecessary(registry, null);
	}

	/**
	 * 必要时注册最基础的 AutoProxyCreator,并指定配置源对象。
	 */
	public static @Nullable BeanDefinition registerAutoProxyCreatorIfNecessary(
			BeanDefinitionRegistry registry, @Nullable Object source) {
		return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
	}

	/**
	 * 必要时注册支持 AspectJ 风格表达式的 AutoProxyCreator。
	 * 若已有更高优先级的实现,则不会重复注册。
	 */
	public static @Nullable BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
		return registerAspectJAutoProxyCreatorIfNecessary(registry, null);
	}

	/**
	 * 必要时注册支持 AspectJ 风格表达式的 AutoProxyCreator,并指定配置源对象。
	 */
	public static @Nullable BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(
			BeanDefinitionRegistry registry, @Nullable Object source) {
		return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source);
	}

	/**
	 * 必要时注册支持 @Aspect 注解风格切面的 AutoProxyCreator。
	 * 这是目前功能最全面、推荐使用的实现。
	 */
	public static @Nullable BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
		return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
	}

	/**
	 * 必要时注册支持 @Aspect 注解风格切面的 AutoProxyCreator,并指定配置源对象。
	 */
	public static @Nullable BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
			BeanDefinitionRegistry registry, @Nullable Object source) {
		return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
	}

	/**
	 * 强制 AutoProxyCreator 使用 CGLIB 来代理目标类(即使目标类实现了接口)。
	 */
	public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
		if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
			BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
			definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
		}
	}

	/**
	 * 强制 AutoProxyCreator 将当前代理对象暴露给 ThreadLocal。
	 * 可用于在 Advice 中获取当前代理实例。
	 */
	public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
		if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
			BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
			definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
		}
	}

	/**
	 * 注册或升级 AOP 自动代理创建器(AutoProxyCreator)。
	 *
	 * 此方法用于在 BeanDefinitionRegistry 中注册指定类型的自动代理创建器 bean,
	 * 如果已存在其他类型的自动代理创建器,则根据优先级决定是否替换它。
	 *
	 * @param cls      要注册的自动代理创建器类(如 InfrastructureAdvisorAutoProxyCreator.class)
	 * @param registry 用来注册 BeanDefinition 的注册表
	 * @param source   配置源对象(可选),用于调试或日志记录
	 * @return 如果新注册了该类型 bean 定义,则返回对应的 BeanDefinition;
	 *         如果只是升级了现有定义或已有相同类型 bean,则返回 null
	 */
	private static @Nullable BeanDefinition registerOrEscalateApcAsRequired(
			Class<?> cls, 
			BeanDefinitionRegistry registry, 
			@Nullable Object source) {
	
		// 参数校验,确保 registry 不为 null
		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
	
		// 检查容器中是否已经存在名为 internalAutoProxyCreator 的 bean 定义
		if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
			// 获取当前存在的自动代理创建器的 BeanDefinition
			BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
	
			// 如果当前存在的类名和要注册的类不同,说明需要判断是否进行替换
			if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
				// 获取当前定义的自动代理创建器的优先级
				int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
				// 获取即将注册的新类的优先级
				int requiredPriority = findPriorityForClass(cls);
	
				// 如果新类优先级更高,则更新为新的类名
				if (currentPriority < requiredPriority) {
					apcDefinition.setBeanClassName(cls.getName());
				}
			}
			// 如果已经存在一个定义,并且不需要替换,则直接返回 null
			return null;
		}
	
		// 如果不存在,则创建一个新的 RootBeanDefinition 实例
		RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
		// 设置配置源(用于调试信息)
		beanDefinition.setSource(source);
		// 设置顺序属性为最高优先级,保证该后处理器最早执行
		beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
		// 标记此 bean 定义为基础设施 bean(不会被用户直接使用)
		beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
		// 将新定义的自动代理创建器注册到容器中
		registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
	
		// 返回新创建的 BeanDefinition
		return beanDefinition;
	}

	/**
	 * 获取指定类在优先级列表中的索引值(索引越小优先级越低)。
	 */
	private static int findPriorityForClass(Class<?> clazz) {
		return APC_PRIORITY_LIST.indexOf(clazz);
	}

	/**
	 * 获取指定类名字符串在优先级列表中的索引值。
	 * 如果未找到,抛出异常。
	 */
	private static int findPriorityForClass(@Nullable String className) {
		for (int i = 0; i < APC_PRIORITY_LIST.size(); i++) {
			Class<?> clazz = APC_PRIORITY_LIST.get(i);
			if (clazz.getName().equals(className)) {
				return i;
			}
		}
		throw new IllegalArgumentException(
				"Class name [" + className + "] is not a known auto-proxy creator class");
	}
}

说明

  • order:设置BeanDefinition的order为最高优先级,保证该后处理器最早执行
  • 优先级顺序:InfrastructureAdvisorAutoProxyCreator < AspectJAwareAdvisorAutoProxyCreator < AnnotationAwareAspectJAutoProxyCreator

2. 🔍3个AutoProxyCreator比较

功能/能力InfrastructureAdvisorAutoProxyCreatorAspectJAwareAdvisorAutoProxyCreatorAnnotationAwareAspectJAutoProxyCreator
仅处理 ROLE_INFRASTRUCTURE 的 Advisor
支持 XML 配置的 AspectJ 切面
支持 @Aspect@Pointcut@Before 等注解
支持 AspectJ 表达式(execution, within 等)
支持切面排序(按声明顺序)
是否支持 <aop:include> 过滤
是否自动识别 @Aspect
优先级012

五、AbstractAutoProxyCreator

1. 简介

  • 3个AutoProxyCreator都继承AbstractAutoProxyCreator
  • 实现BeanPostProcessor

2. getEarlyBeanReference(...) 方法

/**
 * 获取早期 Bean 引用,并决定是否对其进行包装(即创建代理对象)。
 *
 * <p>该方法是 Spring 解决循环依赖机制中的一个重要环节,同时也用于提前为 Bean 创建 AOP 代理。
 * 当一个 Bean 被放入三级缓存中用于解决循环引用时,会调用此方法获取其早期引用(early reference)。
 *
 * <p>具体来说:
 * - 将当前 Bean 放入 earlyBeanReferences 缓存中,标识它是一个早期 Bean
 * - 然后调用 wrapIfNecessary 方法判断是否需要为该 Bean 创建代理对象
 *
 * @param bean     正在被处理的 Bean 实例(尚未完全初始化)
 * @param beanName 该 Bean 在容器中的名称
 * @return 返回原始 Bean 或其代理对象
 */
@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
	// 构建缓存键,用于唯一标识当前 Bean 的类型和名称
	Object cacheKey = getCacheKey(bean.getClass(), beanName);

	// 将当前 Bean 添加到 earlyBeanReferences 缓存中,表示这是一个早期 Bean 引用
	// 放入的是原始 Bean 实例
	this.earlyBeanReferences.put(cacheKey, bean);

	// 判断是否需要对当前 Bean 进行代理包装
	return wrapIfNecessary(bean, beanName, cacheKey);
}

📌 执行时机

  • 出现循环依赖,详见这篇

📌 方法逻辑

步骤功能说明
1构建缓存键(cacheKey):用于唯一标识当前 Bean 的 Class 和 Name
2记录早期 Bean 引用:将当前 Bean(原始 Bean 实例)存入 earlyBeanReferences 缓存,用于后续判断是否已被处理过
3尝试包装 Bean:调用 wrapIfNecessary() 方法,判断并返回该 Bean 的代理对象 或者 原始对象

📚 关联方法

  • getCacheKey(Class<?> beanClass, String beanName)

    根据 Bean 的类和名称生成用于缓存的 key。

  • earlyBeanReferences

    缓存用于存储早期 Bean 引用,避免重复代理和帮助解决循环依赖。

  • wrapIfNecessary(...)

    核心代理创建逻辑:判断是否要代理该 Bean,并返回代理对象 或者 原始对象。

📝 小结

内容说明
作用在 Bean 初始化完成前提供早期引用,并决定是否为其创建 AOP 代理
应用场景- 循环依赖处理
- 提前进行 AOP 代理(如在其他 Bean 依赖它时)
核心行为- 记录 Bean 的早期引用
- 调用 wrapIfNecessary() 方法创建代理(如有需要)
关键机制与 Spring 的三级缓存配合,实现延迟代理创建与循环依赖解决

3. postProcessBeforeInstantiation(...) 方法

/**
 * 在目标 Bean 实例化之前被调用,用于判断是否需要为该 Bean 创建代理对象。
 *
 * <p>该方法是 Spring AOP 中实现自动代理的核心逻辑之一。它在 Spring 容器创建 Bean 实例之前执行,
 * 如果在此阶段返回一个代理对象,则容器将直接使用该代理对象,而不再继续创建原始 Bean 实例。
 *
 * <p>此方法主要处理以下两种情况:
 * 1. 是否跳过当前 Bean(如基础设施类或配置中指定跳过的类)
 * 2. 是否存在自定义 TargetSource,若存在则提前创建代理对象
 *
 * @param beanClass 要实例化的 Bean 的 Class 对象
 * @param beanName  要实例化的 Bean 的名称
 * @return 如果需要创建代理,则返回代理对象;否则返回 null,表示继续按正常流程创建 Bean
 */
@Override
public @Nullable Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
	// 构建缓存键,用于标识当前 Bean 的类型和名称
	Object cacheKey = getCacheKey(beanClass, beanName);

	// 如果没有提供 beanName 或者该 bean 不是通过自定义 TargetSource 创建的,
	// 则检查是否已经处理过该 Bean 的代理状态
	if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
		// 如果已经记录了该 Bean 的代理状态,则直接返回 null,不再处理
		if (this.advisedBeans.containsKey(cacheKey)) {
			return null;
		}
		// 如果是基础设施类(如 Advice、Advisor 等)或者应该跳过代理的类,则标记为不需要代理并返回 null
		if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return null;
		}
	}

	// 如果有自定义的 TargetSource(目标源),则在此阶段创建代理对象
	TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
	if (targetSource != null) {
		// 记录该 bean 是由自定义 TargetSource 创建的
		if (StringUtils.hasLength(beanName)) {
			this.targetSourcedBeans.add(beanName);
		}

		// 获取适用于当前 Bean 的特定拦截器(Advice/Advisor)
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);

		// 创建代理对象
		Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);

		// 缓存代理类的类型信息
		this.proxyTypes.put(cacheKey, proxy.getClass());

		// 返回代理对象,阻止 Spring 继续创建原始 Bean 实例
		return proxy;
	}

	// 没有自定义 TargetSource,继续走正常的 Bean 实例化流程
	return null;
}

📌 说明

步骤功能说明
1构建缓存键(cacheKey):用于唯一标识当前正在处理的 Bean
2是否已处理过该 Bean:如果已在 advisedBeans 中记录其是否需要代理,则直接返回结果
3判断是否跳过代理:如是基础设施类(如 Advisor、Advice)或子类决定跳过(shouldSkip),则标记为 FALSE 并返回 null
4尝试获取自定义 TargetSource:如果存在自定义的目标源,则准备为其创建代理
5获取适用于该 Bean 的拦截器链(specificInterceptors)
6创建代理对象:通过createProxy() 方法生成 AOP 代理
7缓存代理类类型,避免重复处理
8返回代理对象,Spring 将不会继续创建原始 Bean 实例

📚 关键方法

  • getCacheKey(beanClass, beanName)

    生成用于缓存的 key,优先使用 beanName,必要时使用 class。

  • isInfrastructureClass(beanClass)

    判断是否是基础设施类(如 Advice、Pointcut、Advisor、AopInfrastructureBean),这些类不应该被代理。

  • shouldSkip(beanClass, beanName)

    子类可重写此方法以决定某些 Bean 是否应跳过代理(例如为了避免循环依赖)。

  • getCustomTargetSource(beanClass, beanName)

    获取用户自定义的目标源(TargetSource),如池化、原型等特殊场景下使用。

  • getAdvicesAndAdvisorsForBean(...)

    抽象方法,子类必须实现,用于获取适用于当前 Bean 的拦截器链。

  • createProxy(...)

    使用 ProxyFactory 创建 AOP 代理对象。

4. postProcessAfterInitialization(...) 方法

/**
 * 在目标 Bean 初始化完成后被调用,用于决定是否为其创建 AOP 代理对象。
 *
 * <p>该方法是 Spring AOP 中实现自动代理的关键步骤之一。它在 Bean 的所有属性设置和初始化方法(如 init-method)
 * 执行之后被调用。如果在此阶段返回一个代理对象,则容器将使用该代理对象替代原始 Bean 实例。
 *
 * <p>此方法主要完成以下任务:
 * 1. 检查当前 Bean 是否已经被提前代理(early proxying),例如在 {@link #postProcessBeforeInstantiation} 阶段
 * 2. 如果未被提前代理,则根据配置判断是否需要为当前 Bean 创建代理
 *
 * @param bean     初始化完成后的原始 Bean 实例
 * @param beanName 该 Bean 在容器中的名称
 * @return 如果需要代理,返回包装后的代理对象;否则返回原始 Bean 实例
 */
@Override
public @Nullable Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
	// 如果 bean 不为空
	if (bean != null) {
		// 构建缓存键,用于唯一标识当前 Bean 的类型和名称
		Object cacheKey = getCacheKey(bean.getClass(), beanName);

		// 从 earlyBeanReferences 缓存中移除该 bean,判断是否是早期代理的对象
		// 如果不是早期代理的对象,则执行 wrapIfNecessary 方法尝试创建代理
		if (this.earlyBeanReferences.remove(cacheKey) != bean) {
			return wrapIfNecessary(bean, beanName, cacheKey);
		}
	}
	// 返回原始 bean 对象(无需代理)
	return bean;
}

📌 入参bean

  • 没有出现循环依赖:为原始对象
  • 出现循环依赖:调用getEarlyBeanReference(...) 方法,再调用wrapIfNecessary(...) 方法,此时的 bean 为 代理对象 或者 原始对象

📌 说明

步骤功能说明
1检查 bean 是否为 null:若为 null 则直接返回,不做处理
2构建缓存键(cacheKey):用于唯一标识当前 Bean 的 Class 和 Name
3从 earlyBeanReferences 中移除 cacheKey 对应的对象
- 若移除的值与当前 bean 不同,需要进行代理处理
4调用 wrapIfNecessary() 方法:实际创建代理对象的核心逻辑
5返回代理或原始 bean

📚 关键方法

  • getCacheKey(bean.getClass(), beanName)

    生成用于缓存的 key,优先使用 beanName,必要时使用 class。

  • wrapIfNecessary(bean, beanName, cacheKey)

    核心代理创建逻辑:判断是否需要代理、获取拦截器链、创建代理对象等。

  • earlyBeanReferences

    存储早期 Bean 引用的缓存,用于解决循环依赖及避免重复代理。

📝 小结

内容说明
作用在 Bean 初始化完成后决定是否为其创建 AOP 代理对象
执行时机Bean 的 afterPropertiesSet() 或自定义 init-method 调用之后
关键逻辑- 判断是否已在实例化前创建过代理
- 若未提前代理,则调用 wrapIfNecessary() 创建代理
核心方法wrapIfNecessary()
子类扩展点getAdvicesAndAdvisorsForBean(...) :子类必须实现该抽象方法来决定哪些 Bean 需要被代理

5. getCacheKey(...) 方法

/**
 * 为给定的 Bean 类型和名称构建一个缓存键(cache key),用于唯一标识该 Bean。
 *
 * <p>该方法用于在缓存中存储与 Bean 相关的信息(如代理类型、是否已被代理等)时使用。
 * 从 Spring 4.2.3 开始,该实现不再返回将类名和 Bean 名拼接的字符串,
 * 而是采用更高效的策略生成缓存键:
 * - 如果提供了 beanName,则直接使用 beanName;
 * - 若该 Bean 是 FactoryBean 类型,则在其 beanName 前添加 {@link BeanFactory#FACTORY_BEAN_PREFIX} 前缀;
 * - 如果没有提供 beanName,则直接使用 beanClass 作为缓存键。
 *
 * @param beanClass 当前 Bean 的 Class 对象
 * @param beanName  当前 Bean 在容器中的名称(可能为 null)
 * @return 返回用于缓存的键对象,可以是 String 或 Class 类型
 */
protected Object getCacheKey(Class<?> beanClass, @Nullable String beanName) {
	// 如果提供了 beanName,则基于 beanName 构建缓存键
	if (StringUtils.hasLength(beanName)) {
		// 如果该 Bean 是 FactoryBean 类型,则加上 FACTORY_BEAN_PREFIX 前缀
		// 例如:beanName 为 "myBean",且是 FactoryBean,则返回 "&myBean"
		return (FactoryBean.class.isAssignableFrom(beanClass) ?
				BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName);
	}
	else {
		// 如果没有提供 beanName,则直接以 Class 作为缓存键
		return beanClass;
	}
}

6. wrapIfNecessary(...) 方法

/**
 * 如果需要,包装给定的 bean,即如果该 bean 有资格被代理,则为其创建 AOP 代理。
 * 
 * @param bean 原始的 bean 实例
 * @param beanName bean 的名称
 * @param cacheKey 用于元数据访问的缓存键(通常是类或 bean 名称的组合)
 * @return 如果需要代理,则返回代理对象;否则返回原始 bean 实例
 */
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    // 如果 beanName 存在,并且该 bean 已经由自定义 TargetSource 创建,则不需要再代理
    if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
        return bean;
    }

    // 如果该 bean 被标记为不需要代理(advisedBeans 中值为 false),直接返回原对象
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    }

    // 判断当前 bean 是否是基础设施类(如 Advice、Pointcut、Advisor 等),或者是否应该跳过代理处理
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

    // 获取适用于该 bean 的特定拦截器(advice 或 advisor)
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

    // 如果有需要应用的拦截器,则创建代理对象
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);

        // 使用 SingletonTargetSource 包装原始 bean
        // 创建代理对象
        Object proxy = createProxy(
                bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));

        // 缓存代理类的类型
        this.proxyTypes.put(cacheKey, proxy.getClass());

        // 返回代理对象
        return proxy;
    }

    // 如果没有需要应用的拦截器,则标记为不代理,并返回原始 bean
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
}

说明:

  • 该方法负责判断一个 bean 是否需要被 AOP 代理。
  • 如果需要代理,则调用 createProxy 创建代理对象。
  • 各种条件判断用于避免重复代理、跳过基础设施类、以及根据业务逻辑决定是否代理。
  • 通过 getAdvicesAndAdvisorsForBean 获取适用于该 bean 的切面逻辑(拦截器链)。

注:该方法是 Spring AOP 自动代理机制的核心流程之一,常用于 postProcessAfterInitialization 阶段对符合条件的 bean 进行代理封装。

7. getAdvicesAndAdvisorsForBean(...) 方法

一个抽象方法,用于决定是否需要为指定的 Bean 创建代理,并提供适用于该 Bean 的拦截器(Advice)和通知器(Advisor)。

/**
 * 判断给定的 Bean 是否需要被代理,以及需要应用哪些额外的通知(例如 AOP Alliance 拦截器)和通知器。
 *
 * @param beanClass 需要进行增强的 Bean 的类对象
 * @param beanName  需要进行增强的 Bean 的名称
 * @param customTargetSource 由 {@link #getCustomTargetSource} 方法返回的 TargetSource 对象,
 *                          如果没有使用自定义 TargetSource,则为 null。
 * @return 返回适用于该 Bean 的额外拦截器数组;如果不需要额外的拦截器,仅使用公共拦截器,则返回空数组;
 *         如果不需要代理(包括不使用公共拦截器),则返回 null。
 *         可以参考常量 DO_NOT_PROXY 和 PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS。
 * @throws BeansException 如果在获取拦截器或通知器过程中发生错误
 * @see #DO_NOT_PROXY
 * @see #PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS
 */
protected abstract Object @Nullable [] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName,
        @Nullable TargetSource customTargetSource) throws BeansException;

说明:

  • 功能:此方法用于确定目标 Bean 是否需要被代理。如果需要,它还负责返回适用于该 Bean 的一组拦截器和通知器。
  • 参数
    • beanClass:当前正在处理的目标 Bean 的类对象。
    • beanName:目标 Bean 在 Spring 容器中的名称。
    • customTargetSource:可选的自定义目标源,通常由 getCustomTargetSource 方法生成。如果没有自定义目标源,则传入 null
  • 返回值
    • Object[]:包含额外的拦截器和通知器的对象数组。
      • 如果返回 null,表示不创建代理(即使有公共拦截器)。
      • 如果返回空数组 PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS,表示需要创建代理,但只使用公共拦截器。
      • 如果返回非空数组,表示需要创建代理,并且将数组中的拦截器与公共拦截器一起应用。
  • 异常
    • BeansException:当加载拦截器或通知器失败时抛出异常。

使用场景:

该方法是一个模板方法,供子类实现具体的代理逻辑。不同的子类可以基于不同的策略(如根据 Bean 名称、类型、注解等)来决定是否对某个 Bean 进行代理,并提供相应的拦截器和通知器。例如:

  • BeanNameAutoProxyCreator:通过匹配 Bean 名称来决定是否代理。
  • AbstractAdvisorAutoProxyCreator:根据 Advisor 的切点(Pointcut)动态匹配目标 Bean 来决定是否代理。

8. createProxy(...) 方法

/**
 * 为指定的 Bean 创建 AOP 代理对象。
 *
 * @param beanClass 被代理的目标类
 * @param beanName  Bean 的名称
 * @param specificInterceptors 特定于该 Bean 的拦截器数组(可以为空,但不能为 null)
 * @param targetSource 目标源对象,用于获取目标实例
 * @return 返回创建好的 AOP 代理对象
 */
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
		Object @Nullable [] specificInterceptors, TargetSource targetSource) {

	return buildProxy(beanClass, beanName, specificInterceptors, targetSource, false);
}

/**
 * 仅生成代理类的 Class 对象,而不是实例。
 */
private Class<?> createProxyClass(Class<?> beanClass, @Nullable String beanName,
		Object @Nullable [] specificInterceptors, TargetSource targetSource) {

	return (Class<?>) buildProxy(beanClass, beanName, specificInterceptors, targetSource, true);
}

/**
 * 构建 AOP 代理的核心方法。
 *
 * @param beanClass 被代理的目标类
 * @param beanName Bean 名称
 * @param specificInterceptors 特定拦截器(如切面、通知等)
 * @param targetSource 目标对象来源
 * @param classOnly 是否只生成 Class 对象而不创建实例
 * @return 如果 classOnly 为 true,返回代理类;否则返回代理实例
 */
private Object buildProxy(Class<?> beanClass, @Nullable String beanName,
		Object @Nullable [] specificInterceptors, TargetSource targetSource, boolean classOnly) {

	// 暴露目标类信息给容器(用于调试或日志记录)
	if (this.beanFactory instanceof ConfigurableListableBeanFactory clbf) {
		AutoProxyUtils.exposeTargetClass(clbf, beanName, beanClass);
	}

	// 创建 ProxyFactory 并复制当前配置
	ProxyFactory proxyFactory = new ProxyFactory();
	proxyFactory.copyFrom(this);

	// 如果强制使用 CGLIB 代理(proxyTargetClass == true)
	if (proxyFactory.isProxyTargetClass()) {
		// 如果是 JDK 动态代理生成的类或 Lambda 表达式,则添加其所有接口以支持引入增强
		if (Proxy.isProxyClass(beanClass) || ClassUtils.isLambdaClass(beanClass)) {
			for (Class<?> ifc : beanClass.getInterfaces()) {
				proxyFactory.addInterface(ifc);
			}
		}
	}
	else {
		// 否则根据默认策略决定是否使用 CGLIB 或 JDK 动态代理
		if (shouldProxyTargetClass(beanClass, beanName)) {
			proxyFactory.setProxyTargetClass(true);
		}
		else {
			evaluateProxyInterfaces(beanClass, proxyFactory);
		}
	}

	// 构建 Advisor 数组(包括通用和特定的拦截器)
	Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
	proxyFactory.addAdvisors(advisors);
	proxyFactory.setTargetSource(targetSource);
	customizeProxyFactory(proxyFactory); // 子类可扩展点

	// 设置代理是否冻结(不允许后续修改)
	proxyFactory.setFrozen(this.freezeProxy);
	if (advisorsPreFiltered()) {
		proxyFactory.setPreFiltered(true); // 告知代理工厂,拦截器已预过滤
	}

	// 获取合适的类加载器
	ClassLoader classLoader = getProxyClassLoader();
	if (classLoader instanceof SmartClassLoader smartClassLoader &&
			classLoader != beanClass.getClassLoader()) {
		classLoader = smartClassLoader.getOriginalClassLoader(); // 使用原始类加载器
	}

	// 根据 classOnly 决定是生成类还是实例
	return (classOnly ? proxyFactory.getProxyClass(classLoader) : proxyFactory.getProxy(classLoader));
}

说明:

buildProxy(...) 是 Spring AOP 自动代理机制中的核心方法之一。它负责:

  • 配置 ProxyFactory
  • 确定使用 JDK 动态代理 还是 CGLIB 代理,详见这篇
  • 添加 Advisor 链和目标源(TargetSource);
  • 最终生成 代理类代理实例

方法流程:

  1. 暴露目标类信息

    • 通过 AutoProxyUtils.exposeTargetClass(...) 将目标类信息暴露给 BeanFactory,便于后续调试/日志分析。
  2. 初始化 ProxyFactory

    • 创建一个新的 ProxyFactory 实例,并从当前自动代理创建器中复制配置(如 proxyTargetClass、exposeProxy 等)。
  3. 判断代理方式(JDK vs CGLIB)

    • 如果 proxyTargetClass == true:强制使用 CGLIB。
      • 若目标类是动态代理类或 Lambda 表达式,则添加其所有实现的接口,以支持引入增强。
    • 否则调用 shouldProxyTargetClass(...) 判断是否应使用 CGLIB。
      • 如果不是,则尝试通过evaluateProxyInterfaces(...) 使用 JDK 动态代理。
  4. 构建并添加 Advisor 链

    • 通过 buildAdvisors(...) 方法将拦截器(Advice)转换为 Advisor 类型;
    • 将这些 Advisor 添加到 ProxyFactory 中。
  5. 设置 TargetSource

    • 将传入的 TargetSource 设置进 ProxyFactory
  6. 自定义 ProxyFactory

    • 提供给子类扩展的方法 customizeProxyFactory(...) ,用于进一步配置代理工厂。
  7. 设置代理属性

    • 设置代理是否“冻结”(不可再添加 Advice);
    • 如果拦截器已经预先过滤过advisorsPreFiltered() ,则跳过运行时检查。
  8. 选择类加载器

    • 若当前类加载器为 SmartClassLoader 且与目标类不同,则使用原始类加载器,避免类冲突。
  9. 生成代理

    • 如果 classOnly == true:仅生成代理类;
    • 否则:创建代理实例。

关键方法:

方法作用
buildAdvisors(...)将拦截器封装为 Advisor ,供 AOP 使用
shouldProxyTargetClass(...)判断是否应该使用目标类进行代理(即是否启用 CGLIB)
evaluateProxyInterfaces(...)分析目标类接口,决定是否使用 JDK 动态代理
customizeProxyFactory(...)子类可重写此方法来自定义代理工厂行为
getProxyClassLoader()获取用于生成代理类的类加载器

示例:

假设有一个 Service 类:

public class OrderService {
    public void placeOrder() {
        // ...
    }
}

并为其配置了一个切面 LogAspect:

@Aspect
@Component
public class LogAspect {
    @Before("execution(* OrderService.*(..))")
    public void before(JoinPoint joinPoint) {
        System.out.println("Before method: " + joinPoint);
    }
}

Spring 容器在启动时会调用 buildProxy(...) 方法,最终生成一个包装了 OrderService 的代理对象,调用 placeOrder() 时会先执行 LogAspect.before(...),再执行目标方法。

小结:

  • buildProxy(...) 是 Spring AOP 自动代理创建的核心逻辑。
  • buildProxy(...) 决定了代理方式(JDK / CGLIB)、构建拦截器链、设置目标源,并最终生成代理类或实例。
  • 支持灵活的扩展机制(如 customizeProxyFactory ,适合各种复杂场景下的 AOP 应用。

六、AbstractAdvisorAutoProxyCreator

1. 简介

  • 核心功能 —— 根据匹配的通知器(Advisor)动态地为 Bean 创建 AOP 代理
  • 继承AbstractAutoProxyCreator
  • 3个AutoProxyCreator都继承AbstractAdvisorAutoProxyCreator

2. getAdvicesAndAdvisorsForBean(...) 方法

/**
 * 确定给定 Bean 是否需要被代理,并返回适用于该 Bean 的通知(Advice)和通知器(Advisor)。
 *
 * <p>此方法会查找所有可以应用到当前 Bean 的通知器(Advisor),如果找到至少一个,
 * 则返回这些通知器数组,表示需要为该 Bean 创建代理;
 * 如果没有找到任何通知器,则返回 DO_NOT_PROXY,表示不进行代理。
 *
 * @param beanClass 当前要代理的目标 Bean 的类对象
 * @param beanName  当前要代理的目标 Bean 的名称
 * @param targetSource 自定义的目标源(TargetSource),可能为 null
 * @return 返回适用于该 Bean 的拦截器或通知器数组,若不需要代理则返回 DO_NOT_PROXY
 * @throws BeansException 如果在处理过程中发生异常
 */
protected Object @Nullable [] getAdvicesAndAdvisorsForBean(
        Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {

    // 查找适用于当前 Bean 的所有符合条件的通知器
    List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);

    // 如果没有符合条件的通知器,则返回 DO_NOT_PROXY 表示不创建代理
    if (advisors.isEmpty()) {
        return DO_NOT_PROXY;
    }

    // 否则将通知器列表转为数组返回,表示需要创建代理并应用这些通知器
    return advisors.toArray();
}

说明:

  • 功能:判断指定 Bean 是否需要被 AOP 代理,并获取相关的通知器。
  • 逻辑流程
    1. 调用 findEligibleAdvisors 方法查找所有适用于该 Bean 的通知器。
    2. 如果没有找到通知器,则返回 DO_NOT_PROXY,即不创建代理。
    3. 如果有通知器,则将其转换为数组返回,Spring 会根据这些通知器为 Bean 创建代理对象。

使用场景:

该方法是 AOP 自动代理机制的核心方法之一,由 Spring 容器在 Bean 生命周期中调用,用于决定是否对某个 Bean 进行增强(AOP 代理)。

3. findEligibleAdvisors(...) 方法

/**
 * 查找所有适用于当前类的、可以用于自动代理的通知器(Advisor)。
 *
 * <p>该方法会完成以下步骤:
 * 1. 获取所有的候选通知器(通过 {@link #findCandidateAdvisors()})。
 * 2. 过滤出能够应用到当前 Bean 的通知器(通过 {@link #findAdvisorsThatCanApply(List, Class, String)})。
 * 3. 扩展通知器列表(通过 {@link #extendAdvisors(List)}),允许子类添加额外的通知器。
 * 4. 如果有可用的通知器,则根据顺序进行排序(通过 {@link #sortAdvisors(List)})。
 *
 * @param beanClass 当前需要查找通知器的目标 Bean 的类对象
 * @param beanName  当前正在被代理的 Bean 的名称
 * @return 返回符合条件的通知器列表。如果没有任何通知器适用,返回空列表(不会返回 null)
 *
 * @see #findCandidateAdvisors()
 * @see #sortAdvisors(List)
 * @see #extendAdvisors(List)
 */
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    // 1. 获取所有候选的通知器(通常是 Spring 容器中所有类型为 Advisor 的 Bean)
    List<Advisor> candidateAdvisors = findCandidateAdvisors();

    // 2. 过滤出适用于当前 Bean 的通知器(基于切点匹配)
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);

    // 3. 允许子类扩展,添加一些自定义的通知器(例如上下文相关的通知器)
    extendAdvisors(eligibleAdvisors);

    // 4. 如果有通知器,按顺序排序(支持 @Order 注解或 Ordered 接口)
    if (!eligibleAdvisors.isEmpty()) {
        try {
            eligibleAdvisors = sortAdvisors(eligibleAdvisors);
        }
        catch (BeanCreationException ex) {
            throw new AopConfigException("通知器排序失败,可能是由于自定义实现了 Ordered 接口导致的 Bean 创建问题。" +
                    "建议改用 @Order 注解进行排序。", ex);
        }
    }

    // 返回最终筛选并排序后的通知器列表
    return eligibleAdvisors;
}

说明:

  • 功能:此方法是 AbstractAdvisorAutoProxyCreator 中的核心逻辑之一,负责查找、过滤、扩展和排序适用于某个 Bean 的通知器(Advisor)。
  • 主要流程
    1. 获取候选通知器:通常是从 Spring 容器中获取所有类型为 Advisor 的 Bean。
    2. 筛选适用的通知器:使用 AOP 工具类判断哪些通知器可以应用到目标 Bean 上(基于 Pointcut 或者 Introduction 匹配)。
    3. 扩展通知器列表:提供一个钩子方法供子类实现,可动态添加额外的通知器。
    4. 排序通知器:对匹配的通知器按照优先级进行排序,确保拦截顺序可控。
  • 异常处理:在排序过程中若出现 Bean 创建异常,会封装成 AopConfigException 抛出,并提示建议使用 @Order 注解代替 Ordered接口。

使用场景:

该方法由getAdvicesAndAdvisorsForBean()调用,用于决定是否为某个 Bean 创建代理以及为其添加哪些增强逻辑(Advice)。

4. findEligibleAdvisors(...) 方法

/**
 * 查找所有可用于自动代理的候选通知器(Advisor)。
 *
 * <p>该方法通常用于获取 Spring 容器中所有的 Advisor 类型 Bean,
 * 供后续筛选哪些通知器可以应用到目标 Bean 上。
 *
 * @return 返回一个包含所有候选通知器(Advisor)的列表
 * @throws IllegalStateException 如果当前未初始化 advisorRetrievalHelper,抛出异常
 */
protected List<Advisor> findCandidateAdvisors() {
    // 确保 advisorRetrievalHelper 已经初始化
    Assert.state(this.advisorRetrievalHelper != null,
                 "没有可用的 BeanFactoryAdvisorRetrievalHelper,请确认是否已完成初始化");

    // 委托给 advisorRetrievalHelper 来查找容器中所有类型为 Advisor 的 Bean
    return this.advisorRetrievalHelper.findAdvisorBeans();
}

说明:

  • 功能:此方法负责从 Spring 容器中获取所有类型为Advisor的 Bean,作为候选的通知器,用于后续判断哪些可以应用到当前 Bean 上。
  • 子类可以重写AnnotationAwareAspectJAutoProxyCreator 重写此方法用来支持@Aspect
  • 实现细节
    • 使用了 advisorRetrievalHelper 来实际完成查找工作。
    • 通过 Assert.state(...) 确保 advisorRetrievalHelper 已被正确初始化。

使用场景:

该方法被findEligibleAdvisors()调用,是 AOP 自动代理流程的第一步,即获取所有可能的通知器。

5. findAdvisorsThatCanApply(...) 方法

/**
 * 在给定的候选通知器(Advisor)中,查找所有可以应用到指定 Bean 的通知器。
 *
 * <p>该方法会使用 AOP 工具类 {@link AopUtils#findAdvisorsThatCanApply(List, Class)} 来判断
 * 每个 Advisor 是否匹配目标 Bean 的类或方法,从而决定是否将其加入最终的增强逻辑中。
 *
 * @param candidateAdvisors 候选的通知器列表(通常是从 Spring 容器中获取的所有 Advisor)
 * @param beanClass 目标 Bean 的类对象
 * @param beanName  当前正在被代理的 Bean 的名称
 * @return 返回可以应用到该 Bean 的通知器列表
 *
 * @see ProxyCreationContext#getCurrentProxiedBeanName()
 */
protected List<Advisor> findAdvisorsThatCanApply(
        List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

    // 设置当前正在代理的 Bean 名称,供后续处理(如日志、调试等)使用
    ProxyCreationContext.setCurrentProxiedBeanName(beanName);

    try {
        // 使用 AopUtils 工具类筛选出能够应用到当前 Bean 的通知器
        return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
    }
    finally {
        // 清除当前线程中保存的代理 Bean 名称,避免影响其他 Bean 的处理
        ProxyCreationContext.setCurrentProxiedBeanName(null);
    }
}

说明:

  • 功能:从候选通知器中筛选出适用于当前 Bean 的通知器(Advisor),即根据 Pointcut 或者 Introduction 匹配目标 Bean。
  • 实现细节
    • 使用 AopUtils.findAdvisorsThatCanApply(...) 进行实际的匹配判断。
    • 利用 ProxyCreationContext 设置和清理当前正在代理的 Bean 名称,便于上下文追踪。
  • 使用场景:该方法在findEligibleAdvisors()中被调用,用于过滤出真正适用于某个 Bean 的增强逻辑。

关键工具类:

  • AopUtils.findAdvisorsThatCanApply():核心匹配逻辑,基于 Advisor Pointcut 或者 Introduction 匹配目标类或方法。

七、Advisor

PointcutAdvisorIntroductionAdvisor 是 Spring AOP 中两种不同类型的 通知器(Advisor),它们分别用于不同的增强场景。

✅ 1. 核心功能对比

对比维度PointcutAdvisorIntroductionAdvisor
作用定义在特定切点(Pointcut)上执行的通知(Advice),用于拦截方法调用并进行增强(如日志、事务等)。用于为目标类引入新的接口和实现(即 mixin),使目标对象具有额外的功能或接口行为。
匹配粒度支持 类 + 方法级别 的匹配,通过Pointcut判断是否对某个方法进行拦截。只支持 类级别 的匹配,不涉及方法级别的判断。
是否包含切点✅ 包含切点(Pointcut)❌ 不直接包含切点,但可通过ClassFilter进行类级别的过滤。
是否可以引入新接口❌ 不能引入新的接口或行为✅ 可以为目标类动态添加接口及其实现

✅ 2. 接口定义对比

1. PointcutAdvisor

public interface PointcutAdvisor extends Advisor {
    Pointcut getPointcut();
}
  • 功能:提供一个切点Pointcut,用于决定哪些类/方法需要被增强。
  • 应用场景
    • 日志记录
    • 权限控制
    • 事务管理
  • 典型实现
    • DefaultPointcutAdvisor
    • AspectJExpressionPointcutAdvisor

2. IntroductionAdvisor

public interface IntroductionAdvisor extends Advisor, IntroductionInfo {
    ClassFilter getClassFilter();
    void validateInterfaces() throws IllegalArgumentException;
}
  • 功能
    • 提供一个类过滤器ClassFilter ,用于判断该引入通知是否适用于目标类。
    • 提供要引入的接口列表(通过IntroductionInfo 接口)。
    • 验证这些接口是否可以正确引入到目标类上。
  • 应用场景
    • 给目标类动态添加接口和实现(例如监控接口、mixin)
    • 实现“透明”增强,比如 IsModified 接口跟踪对象是否修改过
  • 典型实现
    • DefaultIntroductionAdvisor

✅ 3. 使用示例

示例 1:PointcutAdvisor —— 拦截方法调用

PointcutAdvisor advisor = new DefaultPointcutAdvisor();
advisor.setPointcut(new ClassFilter() {
    @Override
    public boolean matches(Class<?> clazz) {
        return clazz.getName().contains("Service");
    }
});
advisor.setAdvice(new MethodBeforeAdvice() {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("Method is about to be called: " + method.getName());
    }
});
@Aspect
@Component
public class LoggingAspect {
    @Before("execution(* com.example.service.*.*(..))")
    public void logMethodCall(JoinPoint jp) {
        System.out.println("Calling method: " + jp.getSignature().getName());
    }
}

示例 2:IntroductionAdvisor —— 引入接口

public interface Monitorable {
    boolean isModified();
}

public class ModifiedStateIntroductionInterceptor implements MethodInterceptor, IntroductionInfo {
    private boolean modified = false;

    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        if (isModificationMethod(mi.getMethod())) {
            modified = true;
        }
        return mi.proceed();
    }

    // IntroductionInfo 接口方法
    @Override
    public Class<?>[] getInterfaces() {
        return new Class<?>[] { Monitorable.class };
    }

    public boolean isModified() {
        return modified;
    }
}

// 创建 IntroductionAdvisor
IntroductionAdvisor advisor = new DefaultIntroductionAdvisor(
    new ModifiedStateIntroductionInterceptor(), Monitorable.class);

✅ 4. Spring 内部处理逻辑区别

在 Spring AOP 处理过程中,PointcutAdvisorIntroductionAdvisor 会被分别处理:

处理阶段PointcutAdvisorIntroductionAdvisor
匹配方式使用 canApply(PointcutAdvisor.getPointcut(), clazz) 进行类+方法匹配使用 getClassFilter().matches(clazz) 进行类级别匹配
优先级在处理完 IntroductionAdvisor 后再处理优先处理,因为影响代理类型生成(如是否实现新接口)
是否影响代理类型❌ 通常不影响✅ 影响,若引入了接口,则代理必须实现该接口

✅ 5. 总结对比

特性PointcutAdvisorIntroductionAdvisor
是否包含切点✅ 是❌ 否
匹配粒度方法级别类级别
是否可引入新接口❌ 否✅ 是
典型用途方法拦截、增强添加接口与行为
接口方法getPointcut()getClassFilter(), validateInterfaces(), getInterfaces()
实现接口AdvisorAdvisor, IntroductionInfo
常见实现类DefaultPointcutAdvisorDefaultIntroductionAdvisor
是否影响代理类型❌ 否✅ 是

✅ 结论

  • 如果需要 拦截某些方法并执行增强操作(如日志、权限校验),请选择 PointcutAdvisor
  • 如果希望 为目标类增加新的接口行为(如监控、状态追踪),请选择 IntroductionAdvisor
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值