一、引言:为何要将 AOP 动态代理融入 Bean 生命周期
在自定义 AOP 核心功能(例如基于 JDK 或 Cglib 代理)之后,单元测试能验证切面拦截机制是否生效,但这离实际应用还差一大步。为提升框架实用性,我们需要将 AOP 能力无缝嵌入 Spring 容器,让用户仅通过配置即可使用,而无需手动处理代理逻辑(基于 Proxy.newProxyInstance 代理操作中处理方法匹配和方法拦截,对匹配的对象进行自定义的处理操作)。这也正是“将 AOP 动态代理融入 Bean 生命周期”的价值所在。
二、实现思路概览
- 目标:让 Bean 在创建过程中自动完成 AOP 代理的包装,用户只需正常获取 Bean 即可。
- 关键机制:
- 利用
BeanPostProcessor
,尤其其子接口InstantiationAwareBeanPostProcessor
提供的扩展点,可在 Bean 实例化前后插入自定义逻辑。 - 在
AbstractAutowireCapableBeanFactory#createBean(...)
中优先调用自定义扩展逻辑,将代理对象替换原始实例。
- 利用
- 核心流程:
- 遍历容器中所有
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(...)
,该方法会调用所有类型为InstantiationAwareBeanPostProcessor
的postProcessBeforeInstantiation(...)
; - 若返回值非空,则直接返回该 Bean(可能是代理对象),结束生命周期流程。
AOP 动态代理融入到Bean的生命周期中类关系:
工程结构:
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生命周期有两个介入点:
- 初始化后阶段(post-initialization)
这是最常见的介入点,在 Bean 完成实例化、属性注入和初始化方法(如@PostConstruct
标注的方法或init-method
配置的方法)执行完毕后,Spring 会判断当前 Bean 是否需要被 AOP 代理。若需要,则通过AbstractAutoProxyCreator
的postProcessAfterInitialization
方法创建代理对象,替代原始 Bean 存入容器。 - 实例化前阶段(pre-instantiation)
当 Bean 满足特定条件(如配置了@Lookup
注解或需要提前暴露代理对象以解决循环依赖)时,Spring 会在 Bean 实例化之前就创建代理对象。这种情况下,代理对象会先于原始 Bean 存在,原始 Bean 会被包裹在代理对象内部,通过AbstractAutoProxyCreator
的postProcessBeforeInstantiation
方法实现。
所以,按正常编写思路,这里应该实现的是初始化后阶段中完成代理。于是又为了配合我自己加的调用链,就有了以下大改(这里可能不全,建议直接去仓库看)
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
自己拓展的部分给自己挖了不少坑啊…..这一章整整用了一天时间………