mini-Spring 代理篇-AOP:Step 12:将 AOP 动态代理融入 Bean 生命周期

一、引言:为何要将 AOP 动态代理融入 Bean 生命周期

在自定义 AOP 核心功能(例如基于 JDK 或 Cglib 代理)之后,单元测试能验证切面拦截机制是否生效,但这离实际应用还差一大步。为提升框架实用性,我们需要将 AOP 能力无缝嵌入 Spring 容器,让用户仅通过配置即可使用,而无需手动处理代理逻辑(基于 Proxy.newProxyInstance 代理操作中处理方法匹配和方法拦截,对匹配的对象进行自定义的处理操作)。这也正是“将 AOP 动态代理融入 Bean 生命周期”的价值所在。


二、实现思路概览

  1. 目标:让 Bean 在创建过程中自动完成 AOP 代理的包装,用户只需正常获取 Bean 即可。
  2. 关键机制
    • 利用 BeanPostProcessor,尤其其子接口 InstantiationAwareBeanPostProcessor 提供的扩展点,可在 Bean 实例化前后插入自定义逻辑。
    • AbstractAutowireCapableBeanFactory#createBean(...) 中优先调用自定义扩展逻辑,将代理对象替换原始实例。
  3. 核心流程
    • 遍历容器中所有 AspectJExpressionPointcutAdvisor,依据类匹配器(ClassFilter)判断当前 Bean 类是否需要代理;
    • 若匹配,通过 ProxyFactory 创建代理并返回,终止原 Bean 的正常实例化流程;
    • 若无匹配,则继续按原生命周期流程进行 Bean 的创建、属性注入与初始化。

三、核心类结构与代码要点

1. AspectJExpressionPointcutAdvisor(切面封装器)

  • 同时封装切入点表达式、切面逻辑(Advice)和匹配规则(Pointcut);
  • 便于在容器中统一管理多个切面配置。

2. MethodBeforeAdviceInterceptor(方法拦截器)

  • 实现 MethodInterceptor 接口;
  • 在调用目标方法前执行 before(...),然后再继续调用链。

3. ProxyFactory(代理工厂)

  • 根据 AdvisedSupport 信息,选择创建 JDK 动态代理或 Cglib 代理实例。

4. InstantiationAwareBeanPostProcessor(实例化感知 Bean 后处理器)

  • 扩展点接口,继承自 BeanPostProcessor,提供了实例化前、实例化后、属性填充前等更细粒度的生命周期回调;
  • 核心方法:Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;
    • 在 Bean 实例化之前调用,可以直接返回一个对象(例如代理对象)来替代原本要创建的 Bean;
    • 若返回非 null,Spring 将跳过默认的实例化流程和依赖注入流程,直接使用该对象。
  • 在 AOP 场景中,这个接口是切入 Bean 生命周期并替换为代理对象的关键入口

5. DefaultAdvisorAutoProxyCreator(自动代理创建器)

  • 核心实现类,继承 InstantiationAwareBeanPostProcessor
  • postProcessBeforeInstantiation(...) 中判断 Bean 是否匹配所配置切面,如果匹配则构造并返回代理对象,避免继续走后续生命周期。

6. AbstractAutowireCapableBeanFactory#createBean(...)(Bean 生成流程)

  • 在创建 Bean 前优先执行 resolveBeforeInstantiation(...),该方法会调用所有类型为 InstantiationAwareBeanPostProcessorpostProcessBeforeInstantiation(...)
  • 若返回值非空,则直接返回该 Bean(可能是代理对象),结束生命周期流程。


AOP 动态代理融入到Bean的生命周期中类关系

图 13-2

工程结构:

small-spring-step-12
└── src
    ├── main
    │   └── java
    │       └── cn.bugstack.springframework
    │           ├── aop
    │           │   ├── aspectj
    │           │   │   └── AspectJExpressionPointcut.java
    │           │   │   └── AspectJExpressionPointcutAdvisor.java
    │           │   ├── framework 
    │           │   │   ├── adapter
    │           │   │   │   └── MethodBeforeAdviceInterceptor.java
    │           │   │   ├── autoproxy
    │           │   │   │   └── DefaultAdvisorAutoProxyCreator.java
    │           │   │   ├── AopProxy.java
    │           │   │   ├── Cglib2AopProxy.java
    │           │   │   ├── JdkDynamicAopProxy.java
    │           │   │   ├── ProxyFactory.java
    │           │   │   └── ReflectiveMethodInvocation.java
    │           │   ├── AdvisedSupport.java
    │           │   ├── Advisor.java
    │           │   ├── BeforeAdvice.java
    │           │   ├── ClassFilter.java
    │           │   ├── MethodBeforeAdvice.java
    │           │   ├── MethodMatcher.java
    │           │   ├── Pointcut.java
    │           │   ├── PointcutAdvisor.java
    │           │   └── TargetSource.java
    │           ├── beans
    │           │   ├── factory
    │           │   │   ├── config
    │           │   │   │   ├── AutowireCapableBeanFactory.java
    │           │   │   │   ├── BeanDefinition.java
    │           │   │   │   ├── BeanFactoryPostProcessor.java
    │           │   │   │   ├── BeanPostProcessor.java
    │           │   │   │   ├── BeanReference.java
    │           │   │   │   ├── ConfigurableBeanFactory.java
    │           │   │   │   ├── InstantiationAwareBeanPostProcessor.java
    │           │   │   │   └── SingletonBeanRegistry.java
    │           │   │   ├── support
    │           │   │   │   ├── AbstractAutowireCapableBeanFactory.java
    │           │   │   │   ├── AbstractBeanDefinitionReader.java
    │           │   │   │   ├── AbstractBeanFactory.java
    │           │   │   │   ├── BeanDefinitionReader.java
    │           │   │   │   ├── BeanDefinitionRegistry.java
    │           │   │   │   ├── CglibSubclassingInstantiationStrategy.java
    │           │   │   │   ├── DefaultListableBeanFactory.java
    │           │   │   │   ├── DefaultSingletonBeanRegistry.java
    │           │   │   │   ├── DisposableBeanAdapter.java
    │           │   │   │   ├── FactoryBeanRegistrySupport.java
    │           │   │   │   ├── InstantiationStrategy.java
    │           │   │   │   └── SimpleInstantiationStrategy.java  
    │           │   │   ├── support
    │           │   │   │   └── XmlBeanDefinitionReader.java
    │           │   │   ├── Aware.java
    │           │   │   ├── BeanClassLoaderAware.java
    │           │   │   ├── BeanFactory.java
    │           │   │   ├── BeanFactoryAware.java
    │           │   │   ├── BeanNameAware.java
    │           │   │   ├── ConfigurableListableBeanFactory.java
    │           │   │   ├── DisposableBean.java
    │           │   │   ├── FactoryBean.java
    │           │   │   ├── HierarchicalBeanFactory.java
    │           │   │   ├── InitializingBean.java
    │           │   │   └── ListableBeanFactory.java
    │           │   ├── BeansException.java
    │           │   ├── PropertyValue.java
    │           │   └── PropertyValues.java 
    │           ├── context
    │           │   ├── event
    │           │   │   ├── AbstractApplicationEventMulticaster.java 
    │           │   │   ├── ApplicationContextEvent.java 
    │           │   │   ├── ApplicationEventMulticaster.java 
    │           │   │   ├── ContextClosedEvent.java 
    │           │   │   ├── ContextRefreshedEvent.java 
    │           │   │   └── SimpleApplicationEventMulticaster.java 
    │           │   ├── support
    │           │   │   ├── AbstractApplicationContext.java 
    │           │   │   ├── AbstractRefreshableApplicationContext.java 
    │           │   │   ├── AbstractXmlApplicationContext.java 
    │           │   │   ├── ApplicationContextAwareProcessor.java 
    │           │   │   └── ClassPathXmlApplicationContext.java 
    │           │   ├── ApplicationContext.java 
    │           │   ├── ApplicationContextAware.java 
    │           │   ├── ApplicationEvent.java 
    │           │   ├── ApplicationEventPublisher.java 
    │           │   ├── ApplicationListener.java 
    │           │   └── ConfigurableApplicationContext.java
    │           ├── core.io
    │           │   ├── ClassPathResource.java 
    │           │   ├── DefaultResourceLoader.java 
    │           │   ├── FileSystemResource.java 
    │           │   ├── Resource.java 
    │           │   ├── ResourceLoader.java 
    │           │   └── UrlResource.java
    │           └── utils
    │               └── ClassUtils.java
    └── test
        └── java
            └── cn.bugstack.springframework.test
                ├── bean
                │   ├── IUserService.java
                │   ├── UserService.java
                │   └── UserServiceInterceptor.java
                └── ApiTest.java


四、完整流程概览

text复制编辑1. Spring 启动,BeanFactory 扫描到 `DefaultAdvisorAutoProxyCreator` 并注册。
2. 创建某个 Bean 时,调用 `createBean(...)` → `resolveBeforeInstantiation(...)`。
3. 自动代理创建器的 `postProcessBeforeInstantiation(...)` 被调用:
   • 若当前 Bean 类匹配某个 Advisor 的切入点,则构建代理对象并返回。
   • 若不匹配,则返回 null,交由后续创建流程继续。
4. 若获取的是代理对象,该对象将替代原 Bean。
5. 用户通过 `getBean(...)` 获取的 Bean 已包含 AOP 功能,调用方法时即触发切面拦截。

五、实现:

1.定义Advice拦截器链的组件:

在 Spring 框架中,所有的 Advice 都是通过实现 MethodInterceptor 来完成的。环绕通知(Around Advice)本质上就像一个拦截器链,可以在方法调用的前后执行逻辑,而前置通知(Before Advice)、后置通知(After Advice)等则是这种链路中的不同环节。

1.1 BeforeAdvice:

/**
 * 前置通知标记接口,在目标方法执行前调用的增强类型。
 */
public interface BeforeAdvice extends Advice {
}

1.2 MethodBeforeAdvice

/**
 * 方法执行前的回调通知。
 * 在目标方法调用前执行,可用于检查参数、权限等。
 */
public interface MethodBeforeAdvice extends BeforeAdvice {

    void before(Method method, Object[] args, Object target) throws Throwable;

}

2.定义 Advisor 访问者

Advice 是具体的增强逻辑(前置通知、后置通知、环绕通知等)。

Pointcut 用于定义匹配规则(如基于方法名、注解、AspectJ 表达式等)。

PointcutAdvisor 承担了 Pointcut 和 Advice 的组合,Pointcut 用于获取 JoinPoint,而 Advice 决定于 JoinPoint 执行什么操作。

2.1 Advisor

//表示一个“增强器”,封装了具体的增强逻辑(Advice)
public interface Advisor {

    Advice getAdvice();

}

2.2 PointcutAdvisor

/**
 * 带有切点(Pointcut)定义的 Advisor 接口。
 *
 * 该接口不仅封装增强逻辑(Advice),
 * 还包含用于匹配连接点的切点规则(Pointcut),
 * 用于确定在哪些方法上应用对应的增强。
 *
 * 一般用于基于切点表达式的通知配置,
 * 是 Spring AOP 中最常用的 Advisor 类型。
 */
public interface PointcutAdvisor extends Advisor {

    /**
     * 返回此 Advisor 关联的切点(Pointcut),
     * 用于匹配需要应用 Advice 的连接点。
     */
    Pointcut getPointcut();

}

2.3 AspectJExpressionPointcutAdvisor

AspectJExpressionPointcutAdvisor 实现了 PointcutAdvisor 接口,把切面 pointcut、拦截方法 advice 和具体的拦截表达式包装在一起。这样就可以在 xml 的配置中定义一个 pointcutAdvisor 切面拦截器了

/**
 * 基于 AspectJ 表达式的切点通知器(PointcutAdvisor)实现。
 *
 * 该类封装了:
 * - AspectJ 表达式切点(AspectJExpressionPointcut),用于匹配目标方法
 * - 具体的增强逻辑(Advice)
 * - 以及对应的切点表达式字符串(expression)
 *
 * 通过设置表达式和 Advice,Spring AOP 可以在匹配的方法上应用对应的通知。
 */
public class AspectJExpressionPointcutAdvisor implements PointcutAdvisor {

    // AspectJ 表达式切点,负责匹配目标方法
    private AspectJExpressionPointcut pointcut;

    // 具体的增强逻辑(通知)
    private Advice advice;

    // AspectJ 切点表达式字符串
    private String expression;

    /**
     * 设置 AspectJ 表达式
     * @param expression 切点表达式字符串
     */
    public void setExpression(String expression){
        this.expression = expression;
    }

    /**
     * 获取切点对象,延迟初始化
     * @return 切点
     */
    @Override
    public Pointcut getPointcut() {
        if (null == pointcut) {
            pointcut = new AspectJExpressionPointcut(expression);
        }
        return pointcut;
    }

    /**
     * 获取增强逻辑
     * @return Advice 通知对象
     */
    @Override
    public Advice getAdvice() {
        return advice;
    }

    /**
     * 设置增强逻辑
     * @param advice 通知对象
     */
    public void setAdvice(Advice advice){
        this.advice = advice;
    }

}

3.方法拦截器

3.1MethodBeforeAdviceInterceptor

/**
* MethodBeforeAdviceInterceptor 是前置通知(Before Advice)到方法拦截器(MethodInterceptor)的适配器。
*
* 它将具体的 MethodBeforeAdvice 转换成 MethodInterceptor 接口,
* 使得前置通知能够参与统一的拦截器链调用流程。
*
* 作用:
* - 解耦通知接口和拦截器接口,方便将不同类型的通知统一管理和执行。
* - 让前置通知可以像环绕通知一样参与方法调用的拦截器链,实现链式调用。
*/
public class MethodBeforeAdviceInterceptor implements MethodInterceptor {

/**
* 持有具体的前置通知实现
*/
private MethodBeforeAdvice advice;

public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
this.advice = advice;
}

/**
* 拦截方法调用,先执行前置通知,然后继续执行调用链或目标方法
*
* @param methodInvocation 当前方法调用的封装,包含目标对象、方法、参数和拦截器链
*/
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
// 调用前置通知
advice.before(methodInvocation.getMethod(), methodInvocation.getArguments(), methodInvocation.getThis());
// 继续执行调用链,直到执行目标方法
return methodInvocation.proceed();
}
}

4.代理工厂:

/**
 * ProxyFactory 是代理对象的工厂类,
 * 负责根据配置信息创建对应类型的 AOP 代理。
 *
 * 核心职责:
 *  - 持有切面配置(AdvisedSupport)对象,
 *    包含目标对象、方法拦截器链、方法匹配器等信息。
 *  - 根据 advisedSupport 中的配置决定使用哪种代理方式:
 *      * 如果设置为代理目标类(isProxyTargetClass() == true),
 *        则使用基于 CGLIB 的代理(Cglib2AopProxy),
 *      * 否则使用基于 JDK 动态代理(JdkDynamicAopProxy)。
 *  - 提供统一的 getProxy() 方法,返回代理后的对象。
 */
public class ProxyFactory {

    private AdvisedSupport advisedSupport;

    /**
     * 构造函数,注入切面配置信息
     * @param advisedSupport 包含目标对象和代理配置
     */
    public ProxyFactory(AdvisedSupport advisedSupport) {
        this.advisedSupport = advisedSupport;
    }

    /**
     * 创建代理对象的入口方法,
     * 根据配置选择代理方式并返回代理实例
     * @return 代理对象(目标对象的代理)
     */
    public Object getProxy() {
        return createAopProxy().getProxy();
    }

    /**
     * 根据 advisedSupport 的配置决定代理实现类:
     *  - 代理目标类时返回 Cglib2AopProxy 实例
     *  - 否则返回 JdkDynamicAopProxy 实例
     */
    private AopProxy createAopProxy() {
        if (advisedSupport.isProxyTargetClass()) {
            return new Cglib2AopProxy(advisedSupport);
        }
        return new JdkDynamicAopProxy(advisedSupport);
    }

}

5.融入Bean生命周期的自动代理创建者:

  • 普通BeanPostProcessor作用于初始化阶段
  • InstantiationAwareBeanPostProcessor作为增强版,额外作用于实例化阶段和属性注入阶段

5.1 定义InstantiationAwareBeanPostProcessor:

/**
 * 这个接口在 Spring AOP 自动代理中非常关键,
 * 用于实现自动创建代理对象,拦截 Bean 的实例化流程,
 * 从而无侵入地为目标对象生成代理。
 */
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {

    /**
     * 在目标 Bean 实例化之前执行此方法。
     *
     * 该方法可以返回一个对象,该对象会替代原本容器默认创建的 Bean 实例。
     * 换句话说,可以通过返回代理对象等,阻止默认的 Bean 实例化过程。
     *
     * 这对于实现 AOP 自动代理非常重要,因为可以在此阶段返回代理对象,
     * 从而避免后续再去创建原始的目标对象。
     */
    Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;

}

5.2 DefaultAdvisorAutoProxyCreator,自动创建代理的核心类:

/**
 * 自动代理创建器,自动扫描容器中所有的 AspectJExpressionPointcutAdvisor,
 * 根据切点匹配结果对目标Bean生成代理。
 *
 * 实现了 InstantiationAwareBeanPostProcessor,可以在 Bean 实例化前替换成代理对象。
 */
public class DefaultAdvisorAutoProxyCreator implements InstantiationAwareBeanPostProcessor, BeanFactoryAware {

    private DefaultListableBeanFactory beanFactory;

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        // 这里强转是为了方便后续调用 getBeansOfType 方法
        this.beanFactory = (DefaultListableBeanFactory) beanFactory;
    }

    /**
     * 在 Bean 实例化之前尝试返回代理对象。
     * @param beanClass 待创建Bean的类
     * @param beanName  Bean名称
     * @return 如果匹配切面返回代理,否则返回 null 继续创建原Bean
     * @throws BeansException
     */
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        // 排除Spring自身基础设施类,防止循环代理
        if (isInfrastructureClass(beanClass)) {
            return null;
        }

        // 获取所有切面通知组合对象
        Collection<AspectJExpressionPointcutAdvisor> advisors =
                beanFactory.getBeansOfType(AspectJExpressionPointcutAdvisor.class).values();

        for (AspectJExpressionPointcutAdvisor advisor : advisors) {
            // 判断切面切点是否匹配当前Bean类型
            ClassFilter classFilter = advisor.getPointcut().getClassFilter();
            if (!classFilter.matches(beanClass)) {
                continue;
            }

            // 准备代理相关配置
            AdvisedSupport advisedSupport = new AdvisedSupport();

            //直接用反射创建新对象,跳过 Spring 容器管理
            /*
            TargetSource targetSource = null;
            try {
                targetSource = new TargetSource(beanClass.getDeclaredConstructor().newInstance());
            } catch (Exception e) {
                e.printStackTrace();
            }

            */

            // 通过beanFactory获取目标Bean实例(非重复创建)
            Object target = beanFactory.getBean(beanName);
            advisedSupport.setTargetSource(new TargetSource(target));

            // 添加拦截器链,这里简单添加单个Advice的拦截器
            advisedSupport.addMethodInterceptor((MethodInterceptor) advisor.getAdvice());

            // 设置方法匹配器
            advisedSupport.setMethodMatcher(advisor.getPointcut().getMethodMatcher());

            // 是否使用Cglib代理(这里默认JDK代理)
            advisedSupport.setProxyTargetClass(false);

            // 通过代理工厂生成代理对象并返回
            return new ProxyFactory(advisedSupport).getProxy();
        }

        // 无匹配切面,返回null表示继续创建原Bean
        return null;
    }

    /**
     * 判断是否为Spring基础设施类,避免代理这些类。
     */
    private boolean isInfrastructureClass(Class<?> beanClass) {
        return Advice.class.isAssignableFrom(beanClass) ||
                Pointcut.class.isAssignableFrom(beanClass) ||
                Advisor.class.isAssignableFrom(beanClass);
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // 不做处理,直接返回原始bean
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // 不做处理,直接返回原始bean
        return bean;
    }

}

6.融入到Bean的生命周期:

写到这,看到教程里:

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {

    private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();

    @Override
    protected Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) throws BeansException {
        Object bean = null;
        try {
            // 判断是否返回代理 Bean 对象
            bean = resolveBeforeInstantiation(beanName, beanDefinition);
            if (null != bean) {
                return bean;
            }

            bean = createBeanInstance(beanDefinition, beanName, args);
            // 给 bean 填充属性
            applyPropertyValues(beanName, bean, beanDefinition);
            // 执行 Bean 的初始化方法和 BeanPostProcessor 的前置和后置处理方法
            bean = initializeBean(beanName, bean, beanDefinition);
        } catch (Exception e) {
            throw new BeansException("Instantiation of bean failed.", e);
        }

        // 注册实现了 DisposableBean 接口的 Bean 对象
        registerDisposableBeanIfNecessary(beanName, bean, beanDefinition);

        // 判断 SCOPE_SINGLETON,SCOPE_PROTOTYPE
        if (beanDefinition.isSingleton()) {
            registerSingleton(beanName, bean);
        }
        return bean;
    }

    protected Object resolveBeforeInstantiation(String beanName, BeanDefinition beanDefinition) {
        Object bean = applyBeanPostProcessorBeforeInstantiation(beanDefinition.getBeanClass(), beanName);
        if (null != bean) {
            bean = applyBeanPostProcessorAfterInitialization(bean, beanName);
        }
        return bean;
    }

    // 注意,此方法为新增方法,与 “applyBeanPostProcessorBeforeInitialization” 是两个方法
    public Object applyBeanPostProcessorBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            if (processor instanceof InstantiationAwareBeanPostProcessor) {
                Object result = ((InstantiationAwareBeanPostProcessor)processor).postProcessBeforeInstantiation(beanClass, beanName);
                if (null != result) return result;
            }
        }
        return null;
    }
}

大的要来了!开始大修:

看到上面对craeate的更新,就有了疑问?怎么这里进行aop代理的动作写在了实例化之前?这样得到的bean连属性注入都没有做,完全不能用啊?教程里也没啥为什么这么做就直接添加到那了。所以通过看源码、找解析视屏发现:

aop代理操作在Bean生命周期有两个介入点:

  1. 初始化后阶段(post-initialization)
    这是最常见的介入点,在 Bean 完成实例化、属性注入和初始化方法(如@PostConstruct标注的方法或init-method配置的方法)执行完毕后,Spring 会判断当前 Bean 是否需要被 AOP 代理。若需要,则通过AbstractAutoProxyCreatorpostProcessAfterInitialization方法创建代理对象,替代原始 Bean 存入容器。
  2. 实例化前阶段(pre-instantiation)
    当 Bean 满足特定条件(如配置了@Lookup注解或需要提前暴露代理对象以解决循环依赖)时,Spring 会在 Bean 实例化之前就创建代理对象。这种情况下,代理对象会先于原始 Bean 存在,原始 Bean 会被包裹在代理对象内部,通过AbstractAutoProxyCreatorpostProcessBeforeInstantiation方法实现。

所以,按正常编写思路,这里应该实现的是初始化后阶段中完成代理。于是又为了配合我自己加的调用链,就有了以下大改(这里可能不全,建议直接去仓库看)

DefaultAdvisorAutoProxyCreator:

@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
    // 目前先直接返回null,后期处理循环依赖问题时才需要提前创建代理对象并暴露
    return null;
}
@Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // 排除Spring自身基础设施类,防止循环代理
        if (isInfrastructureClass(bean.getClass())) {
            return bean; // 不代理,直接返回原对象
        }

        // 获取所有切面通知组合对象
        Collection<AspectJExpressionPointcutAdvisor> advisors =
                beanFactory.getBeansOfType(AspectJExpressionPointcutAdvisor.class).values();


        //直接用反射创建新对象,跳过 Spring 容器管理
            /*
            TargetSource targetSource = null;
            try {
                targetSource = new TargetSource(beanClass.getDeclaredConstructor().newInstance());
            } catch (Exception e) {
                e.printStackTrace();
            }

            */

        // 准备代理相关配置
        AdvisedSupport advisedSupport = new AdvisedSupport();
        advisedSupport.setTargetSource(new TargetSource(bean));
        advisedSupport.setProxyTargetClass(bean.getClass().getInterfaces().length == 0);


        // 遍历所有的切面通知器(Advisor)
        for (AspectJExpressionPointcutAdvisor advisor : advisors) {
            // 检查当前通知器的切入点是否匹配目标Bean的类
            // getClassFilter()获取类过滤器,matches()判断目标类是否符合切入点表达式
            if (advisor.getPointcut().getClassFilter().matches(bean.getClass())) {
                // 如果匹配,则将该通知器添加到通知支持类中
                advisedSupport.addAdvisor(advisor); // 存储匹配的通知器
            }
        }

        // 检查是否有匹配的通知器
        if (!advisedSupport.getAdvisors().isEmpty()) {
            // 如果有匹配的通知器,使用代理工厂创建代理对象并返回
            return new ProxyFactory(advisedSupport).getProxy();
        }
        // 如果没有匹配的通知器,直接返回原始Bean对象
        return bean;
    }

所有aop组合在xml被读取后注册为 AspectJExpressionPointcutAdvisor bean。这里beanFactory.getBeansOfType(AspectJExpressionPointcutAdvisor.class).values();读取到全部的aop组合。按类匹配,得到所有的符合条件的advisors存入 advisedSupport。

advisedSupport:

从管理MethodInterceptor到管理PointcutAdvisor。

// 改成存 Advisor 列表,而非 MethodInterceptor 列表
    private List<PointcutAdvisor> advisors = new ArrayList<>();
// ========== getter/setter ==========

TargetSource:

解决了实例化时被cglib代理,之后aop代理时,如果使用jdk方法就找不到原类接口的问题。

/**
 * 封装被代理的目标对象,提供目标实例和类型信息
 */
public class TargetSource {

    private final Object target;

    public TargetSource(Object target) {
        this.target = target;
    }

    /**
     * 获取目标对象的实际类型(类)
     * 例如:UserService.class
     */
    public Class<?> getTargetType() {
        return this.target.getClass();
    }

    /**
     * 获取目标对象实现的所有接口
     * 例如:[IUserService.class]
     */
    public Class<?>[] getTargetInterfaces() {
        return getTargetType().getInterfaces();
    }

    /**
     * 获取目标对象实例
     */
    public Object getTarget() {
        return this.target;
    }

    public Class<?> getTargetClass() {
        // 返回原始类类型,而不是接口
        // 如果目标是代理类(比如 CGLIB 生成的),也能返回其父类
        Class<?> clazz = this.target.getClass();
        // 防止 CGLIB 子类导致的接口丢失问题
        if (clazz.getName().contains("$$")) {
            return clazz.getSuperclass();
        }
        return clazz;
    }

}

两个动态代理实现类:

JdkDynamicAopProxy:

配合advisedSupport的变化。另外下面的部分处理实际应该使用适配器模式转换。

/**
* 基于 JDK 动态代理的 AOP 代理实现类。
* 通过实现 InvocationHandler 接口,实现对目标对象方法的拦截和增强。
*/
public class JdkDynamicAopProxy implements AopProxy, InvocationHandler {

/**
* 封装了被代理对象、方法匹配器和方法拦截器等信息的配置类
*/
private final AdvisedSupport advised;

/**
* 构造函数,传入被代理的配置信息
* @param advised 代理相关的配置,包括目标对象、方法匹配器、拦截器等
*/
public JdkDynamicAopProxy(AdvisedSupport advised) {
this.advised = advised;
}

/**
* 创建并返回目标对象的 JDK 动态代理对象
* @return 代理对象,类型为目标对象的接口类型
*/
@Override
public Object getProxy() {
// 使用当前线程上下文类加载器,目标类接口列表,以及当前对象(作为 InvocationHandler)
// 1. 获取目标对象的Class(如UserService.class)
Class<?> targetClass = advised.getTargetSource().getTargetClass();

//debug:
//System.out.println("目标类:" + targetClass.getName());

// 2. 获取目标对象实现的所有接口(关键:必须是接口数组)
Class<?>[] interfaces = targetClass.getInterfaces();

// 3. 验证是否有接口(JDK代理必须基于接口)
if (interfaces.length == 0) {
throw new BeansException("目标类 " + targetClass.getName() + " 未实现任何接口,无法使用JDK动态代理");
}

//debug:
// for (Class<?> iface : interfaces) {
// //System.out.println("代理实现的接口:" + iface.getName());
// // 应输出:com.miniSpring.test.bean.IUserService
// }


// 4. 传入接口数组创建代理
return Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
interfaces, // 正确:传入接口数组(如[IUserService.class])
this
);
}

/**
* 代理对象的方法调用处理逻辑,实现了方法拦截增强功能
* @param proxy 代理对象本身(一般不直接使用)
* @param method 被调用的方法
* @param args 方法参数
* @return 方法调用结果
* @throws Throwable 方法执行过程中抛出的异常
*/

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 1. 检查是否是Object类的方法(如toString、hashCode等),这些方法通常不需要增强
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(advised.getTargetSource().getTarget(), args);
}


// 2. 获取匹配的Advisor
List<PointcutAdvisor> eligibleAdvisors = new ArrayList<>();
for (PointcutAdvisor advisor : advised.getAdvisors()) {
if (advisor.getPointcut().getMethodMatcher()
.matches(method, advised.getTargetSource().getTarget().getClass())) {
eligibleAdvisors.add(advisor);
}
}

// 3. 把Advisor转换成MethodInterceptor链
List<MethodInterceptor> interceptorChain = new ArrayList<>();
for (Advisor advisor : eligibleAdvisors) {
// 获取当前Advisor对应的Advice(增强逻辑)
Advice advice = advisor.getAdvice();

if (advice instanceof MethodInterceptor) {
// 如果Advice本身就是MethodInterceptor,直接加入拦截器链
interceptorChain.add((MethodInterceptor) advice);
} else if (advice instanceof MethodBeforeAdvice) {
// 如果是前置通知接口,使用MethodBeforeAdviceInterceptor适配成MethodInterceptor
interceptorChain.add(new MethodBeforeAdviceInterceptor((MethodBeforeAdvice) advice));
} else {
// 目前不支持的Advice类型,抛出异常提示
throw new IllegalArgumentException("Unsupported advice type: " + advice.getClass());
}
}

// 4. 创建方法调用器,封装目标对象、方法、参数和拦截器链
ReflectiveMethodInvocation invocation = new ReflectiveMethodInvocation(
advised.getTargetSource().getTarget(),
method,
args,
interceptorChain
);

// 5. 执行拦截器链(责任链模式),最终调用目标方法
return invocation.proceed();

}


}

Cglib2AopProxy:

public class Cglib2AopProxy implements AopProxy {

    private final AdvisedSupport advised;

    public Cglib2AopProxy(AdvisedSupport advised) {
        this.advised = advised;
    }

    @Override
    public Object getProxy() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(advised.getTargetSource().getTarget().getClass());
        enhancer.setInterfaces(advised.getTargetSource().getTargetInterfaces());
        enhancer.setCallback(new DynamicAdvisedInterceptor(advised));
        return enhancer.create();
    }

    /**
     * CGLIB 的 MethodInterceptor
     * 负责拦截目标对象的方法调用,执行拦截器链或直接调用目标方法
     */
    private static class DynamicAdvisedInterceptor implements MethodInterceptor {

        private final AdvisedSupport advised;

        public DynamicAdvisedInterceptor(AdvisedSupport advised) {
            this.advised = advised;
        }

        @Override
        public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            // 1. 检查是否是Object类的方法(如toString、hashCode等),这些方法通常不需要增强
            if (Object.class.equals(method.getDeclaringClass())) {
                return method.invoke(advised.getTargetSource().getTarget(), args);
            }


            // 2. 获取匹配的Advisor
            List<PointcutAdvisor> eligibleAdvisors = new ArrayList<>();
            for (PointcutAdvisor advisor : advised.getAdvisors()) {
                if (advisor.getPointcut().getMethodMatcher()
                        .matches(method, advised.getTargetSource().getTarget().getClass())) {
                    eligibleAdvisors.add(advisor);
                }
            }

            // 3. 把Advisor转换成MethodInterceptor链
            List<org.aopalliance.intercept.MethodInterceptor> interceptorChain = new ArrayList<>();
            for (Advisor advisor : eligibleAdvisors) {
                // 获取当前Advisor对应的Advice(增强逻辑)
                Advice advice = advisor.getAdvice();

                if (advice instanceof org.aopalliance.intercept.MethodInterceptor) {
                    // 如果Advice本身就是MethodInterceptor,直接加入拦截器链
                    interceptorChain.add((org.aopalliance.intercept.MethodInterceptor) advice);
                } else if (advice instanceof MethodBeforeAdvice) {
                    // 如果是前置通知接口,使用MethodBeforeAdviceInterceptor适配成MethodInterceptor
                    interceptorChain.add(new MethodBeforeAdviceInterceptor((MethodBeforeAdvice) advice));
                } else {
                    // 目前不支持的Advice类型,抛出异常提示
                    throw new IllegalArgumentException("Unsupported advice type: " + advice.getClass());
                }
            }

                // 执行拦截器链,传入自定义的 CglibMethodInvocation
                CglibMethodInvocation invocation = new CglibMethodInvocation(
                        advised.getTargetSource().getTarget(),
                        method,
                        args,
                        methodProxy,
                        interceptorChain
                );
                return invocation.proceed();
        }
    }

    /**
     * CglibMethodInvocation 继承 ReflectiveMethodInvocation,复用拦截器链调用逻辑,
     * 并重写 proceed() 用 CGLIB 的 methodProxy 来调用目标方法,避免反射调用。
     */
    private static class CglibMethodInvocation extends ReflectiveMethodInvocation {

        private final MethodProxy methodProxy;

        public CglibMethodInvocation(Object target, Method method, Object[] arguments,
                                     MethodProxy methodProxy, List<org.aopalliance.intercept.MethodInterceptor> interceptors) {
            super(target, method, arguments, interceptors);
            this.methodProxy = methodProxy;
        }

        @Override
        public Object proceed() throws Throwable {
            if (currentInterceptorIndex == methodInterceptorList.size() - 1) {
                // 所有拦截器执行完后,使用 CGLIB 方式调用目标方法,效率更高
                return methodProxy.invoke(target, arguments);
            }
            currentInterceptorIndex++;
            org.aopalliance.intercept.MethodInterceptor interceptor = methodInterceptorList.get(currentInterceptorIndex);
            return interceptor.invoke(this);
        }
    }
}

同上。

测试:

xml配置:

注:拦截器的生效顺序由于是被注册为bean,存储在hashmap中,所以暂时不可用,后续可以添加“基于优先级的排序”机制实现控制排序。

<?xml version="1.0" encoding="UTF-8"?>
<beans>
    <!-- 代理目标:-->
    <bean id="userService" class="com.miniSpring.test.bean.UserService">
        <property name="uId" value="10001"/>
        <property name="name" value="CMD137"/>
    </bean>

    <!-- 自动代理创建器:-->
    <bean class="com.miniSpring.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>

    <!-- aop组合1-->
    <bean id="beforeAdvice1" class="com.miniSpring.test.bean.PerformanceInterceptor"/>

    <bean id="methodInterceptor1" class="com.miniSpring.aop.adapter.MethodBeforeAdviceInterceptor">
        <property name="advice" ref="beforeAdvice1"/>
    </bean>

    <bean id="pointcutAdvisor1" class="com.miniSpring.aop.aspectj.AspectJExpressionPointcutAdvisor">
        <property name="expression" value="execution(* com.miniSpring.test.bean.IUserService.*(..))"/>
        <property name="advice" ref="methodInterceptor1"/>
    </bean>

    <!-- aop组合2-->
    <bean id="beforeAdvice2" class="com.miniSpring.test.bean.OrderInterceptor"/>

    <bean id="methodInterceptor2" class="com.miniSpring.aop.adapter.MethodBeforeAdviceInterceptor">
        <property name="advice" ref="beforeAdvice2"/>
    </bean>

    <bean id="pointcutAdvisor2" class="com.miniSpring.aop.aspectj.AspectJExpressionPointcutAdvisor">
        <property name="expression" value="execution(* com.miniSpring.test.bean.IUserService.*(..))"/>
        <property name="advice" ref="methodInterceptor2"/>
    </bean>

</beans>

单元测试1:

@Test
    public void testInterceptor() {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
        IUserService userService = applicationContext.getBean("userService", IUserService.class);
        System.out.println("测试结果:" + userService.queryUserName());
    }

结果:

监控拦截器 - Before 拦截方法名称:queryUserName
OrderInterceptor拦截器 - Before: 拦截方法名称:queryUserName
UserService.queryUserName 原方法执行: CMD137---------10086
测试结果:CMD137,10086

自己拓展的部分给自己挖了不少坑啊…..这一章整整用了一天时间………

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇