这章的原标题“给代理对象的属性设置值”,就是把创建代理对象的步骤从在整个创建 Bean 对象之前(不算在 Bean 生命周期中)融入到 Bean 的生命周期中,也就是需要把创建代理对象的逻辑迁移到 Bean 对象执行初始化方法之后,在执行代理对象的创建。但是我已经提前完成了…
见mini-Spring 代理篇-AOP:Step 12:将 AOP 动态代理融入 Bean 生命周期 – CMD137’s Blog之“大的要来了!开始大修”。
那么这一章就来补全aop的其他方法(after、around),完善可排序的拦截器链。系统性的梳理一下整个aop系统。
0.做点小优化:
TargetSource
public Class<?> getTargetClass() {
// 返回原始类类型,而不是接口
// 如果目标是代理类(比如 CGLIB 生成的),也能返回其父类
Class<?> clazz = this.target.getClass();
// 防止 CGLIB 子类导致的接口丢失问题
if (clazz.getName().contains("$$")) {
return clazz.getSuperclass();
}
return clazz;
}
原来的.contains(“$$”)不够优雅,所以:
public Class<?> getTargetClass() {
Class<?> clazz = this.target.getClass();
clazz = ClassUtils.isCglibProxyClass(clazz) ? clazz.getSuperclass() : clazz;
return clazz;
}
(虽然工具类内部也是.contains(“$$”)…)
1.补充after、around:
1.1 after:
1.1.1 AfterAdvice:
/**
* 后置通知标记接口,在目标方法执行后调用的增强类型。
*/
public interface AfterAdvice extends Advice {
}
1.1.2 MethodAfterAdvice:
import java.lang.reflect.Method;
/**
* 方法执行后的回调通知。
* 在目标方法调用后执行,可用于日志记录、清理资源等操作。
*/
public interface MethodAfterAdvice extends AfterAdvice {
/**
* 目标方法执行后调用
*/
void after(Method method, Object[] args, Object target, Object returnValue) throws Throwable;
}
1.1.3 MethodAfterAdviceInterceptor:
/**
* MethodAfterAdviceInterceptor 是后置通知(After Advice)到方法拦截器(MethodInterceptor)的适配器。
*
* 它将具体的 MethodAfterAdvice 转换成 MethodInterceptor 接口,
* 使得后置通知能够参与统一的拦截器链调用流程。
*
* 作用:
* - 解耦通知接口和拦截器接口,方便将不同类型的通知统一管理和执行。
* - 让后置通知可以像环绕通知一样参与方法调用的拦截器链,实现链式调用。
*/
public class MethodAfterAdviceInterceptor implements MethodInterceptor {
/**
* 持有具体的后置通知实现
*/
private MethodAfterAdvice advice;
// 添加无参构造函数,用于实例化(关键)
public MethodAfterAdviceInterceptor() {
}
public MethodAfterAdviceInterceptor(MethodAfterAdvice advice) {
this.advice = advice;
}
/**
* 拦截方法调用,先执行目标方法,然后执行后置通知
*
* @param methodInvocation 当前方法调用的封装,包含目标对象、方法、参数和拦截器链
*/
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
// 执行调用链,最终执行目标方法
Object returnValue = methodInvocation.proceed();
// 调用后置通知
advice.after(methodInvocation.getMethod(), methodInvocation.getArguments(),
methodInvocation.getThis(), returnValue);
return returnValue;
}
}
1.2 Around:
1.2.1 AroundAdvice
/**
* 环绕通知标记接口。
* 环绕通知可以在目标方法执行前后都进行增强操作,
* 并且可以控制是否执行目标方法。
*/
public interface AroundAdvice extends Advice {
}
1.2.2 MethodAroundAdvice
import java.lang.reflect.Method;
/**
* 方法执行前后都可增强的回调通知。
* 环绕通知可以决定是否执行目标方法,并可在执行前后添加自定义逻辑。
*/
public interface MethodAroundAdvice extends AroundAdvice {
/**
* 环绕通知方法
*/
Object around(Method method, Object[] args, Object target, MethodInvocation invocationMethodChain) throws Throwable;
}
这里
MethodInvocation
可以让环绕通知控制是否调用目标方法,或者在调用前后做逻辑。
1.2.3 MethodAroundAdviceInterceptor
/**
* MethodAroundAdviceInterceptor 是环绕通知到方法拦截器的适配器。
*
* 它将具体的 MethodAroundAdvice 转换成 MethodInterceptor 接口,
* 使环绕通知可以参与统一的拦截器链调用流程。
*/
public class MethodAroundAdviceInterceptor implements MethodInterceptor {
private MethodAroundAdvice advice;
// 添加无参构造函数,用于实例化(关键)
public MethodAroundAdviceInterceptor() {
}
public MethodAroundAdviceInterceptor(MethodAroundAdvice advice) {
this.advice = advice;
}
/**
* 拦截方法调用,将环绕通知委托给 MethodAroundAdvice
*/
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
return advice.around(
methodInvocation.getMethod(),
methodInvocation.getArguments(),
methodInvocation.getThis(),
methodInvocation
);
}
}
注意:around与其他两个相比,特殊在环绕通知内部自己决定什么时候调用 invocation.proceed()
,甚至可以完全不调用,从而阻止方法执行或替换返回值。
所以要在具体实现方法中主动/调用目标方法或下一个拦截器:
Object returnValue = invocation.proceed();
1.3 测试
三个拦截方法:
public class LogBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("前置通知: 方法 " + method.getName() + " 即将执行");
}
}
public class LogAfterAdvice implements MethodAfterAdvice {
@Override
public void after(Method method, Object[] args, Object target, Object returnValue) throws Throwable {
System.out.println("后置通知: 方法 " + method.getName() + " 执行完毕, 返回值: " + returnValue);
}
}
public class LogAroundAdvice implements MethodAroundAdvice {
@Override
public Object around(Method method, Object[] args, Object target, MethodInvocation invocation) throws Throwable {
System.out.println("环绕通知: 方法 " + method.getName() + " 执行前");
Object returnValue = invocation.proceed(); // 执行目标方法或下一个拦截器
System.out.println("环绕通知: 方法 " + method.getName() + " 执行后, 返回值: " + returnValue);
return returnValue;
}
}
xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean class="com.miniSpring.beans.factory.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:token.properties"/>
</bean>
<!-- 自动代理创建器:-->
<bean class="com.miniSpring.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
<!-- aop组合1-->
<bean id="beforeAdvice1" class="com.miniSpring.test.bean.LogBeforeAdvice"/>
<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="afterAdvice2" class="com.miniSpring.test.bean.LogAfterAdvice"/>
<bean id="methodInterceptor2" class="com.miniSpring.aop.adapter.MethodAfterAdviceInterceptor">
<property name="advice" ref="afterAdvice2"/>
</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>
<!-- aop组合3-->
<bean id="beforeAdvice3" class="com.miniSpring.test.bean.LogAroundAdvice"/>
<bean id="methodInterceptor3" class="com.miniSpring.aop.adapter.MethodAroundAdviceInterceptor">
<property name="advice" ref="beforeAdvice3"/>
</bean>
<bean id="pointcutAdvisor3" class="com.miniSpring.aop.aspectj.AspectJExpressionPointcutAdvisor">
<property name="expression" value="execution(* com.miniSpring.test.bean.IUserService.*(..))"/>
<property name="advice" ref="methodInterceptor3"/>
</bean>
<component-scan base-package="com.miniSpring.test.bean"/>
</beans>
单元测试:
@Test
public void test() {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
IUserService userService = applicationContext.getBean("userService", IUserService.class);
System.out.println("测试结果:" + userService.queryUserInfo());
}
测试结果:
前置通知: 方法 queryUserInfo 即将执行
环绕通知: 方法 queryUserInfo 执行前
环绕通知: 方法 queryUserInfo 执行后, 返回值: CMD137,北京,亦庄,123_TEST_TOKEN_321
后置通知: 方法 queryUserInfo 执行完毕, 返回值: CMD137,北京,亦庄,123_TEST_TOKEN_321
测试结果:CMD137,北京,亦庄,123_TEST_TOKEN_321
可以看到aop都实现了,那么问题来了。顺序怎么决定的。这里由于都是注册为bean,放在hashmap里,所以执行的顺序是不可掌握的,所以接下来就让我们实现可确定顺序的aop链。
2.实现切面排序机制:
2.1 借鉴真实 Spring 的 AOP 设计思路
在真实的 Spring 框架中,AOP 并不是简单地直接执行 Advice(通知方法),而是通过**一条拦截器链(Interceptor Chain)**来完成的。
执行流程大致如下:
- 收集所有符合当前方法的 Advisor(切面定义)
- 将 Advisor 转换为
MethodInterceptor
(方法拦截器) - 按照
order
顺序对拦截器链排序 - 依次执行拦截器,最终调用目标方法
Spring 里的关键角色:
- Advisor:切面定义,包含 Pointcut(切入点)+ Advice(通知逻辑)
- Advice:通知逻辑,比如 Before、After、Around
- MethodInterceptor:统一的执行接口,拦截调用并执行增强逻辑
- AdvisorAdapterRegistry:适配器注册中心,把不同类型的 Advice 适配成
MethodInterceptor
我们 miniSpring 也沿用了这个思路,只是做了简化,把 AdvisorAdapterRegistry
逻辑直接放在了 DefaultAdvisorAutoProxyCreator
里进行“逻辑适配”。、
2.1 为什么要用适配器模式?
在 AOP 中,有多种类型的 Advice:
MethodBeforeAdvice
(前置通知)MethodAfterAdvice
(后置通知)MethodAroundAdvice
(环绕通知)
如果我们让代理类直接依赖这些接口,就会出现一个问题:
代理类必须写很多 if/else 来区分 Advice 类型,代码耦合度高,不好扩展。
Spring 的做法是——适配器模式:
- 为每种 Advice 提供一个适配器,比如:
MethodBeforeAdviceInterceptor
- 这些适配器统一实现
MethodInterceptor
接口 - 代理类只需要和
MethodInterceptor
打交道,不关心底层是 before 还是 after
miniSpring 的适配器类示例:
public class MethodBeforeAdviceInterceptor implements MethodInterceptor {
private final MethodBeforeAdvice advice;
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
this.advice = advice;
}
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
advice.before(invocation.getMethod(), invocation.getArguments(), invocation.getThis());
return invocation.proceed();
}
}
具体来说,适配器MethodBeforeAdviceInterceptor 让适配者MethodBeforeAdvice 实现了MethodInterceptor 接口,从而可以调用invoke方法
2.3 Advisor 的顺序排序机制
一个常见的 AOP 场景是:
先执行一个日志切面,再执行一个事务切面。
如果没有顺序控制,切面的执行顺序就会变得不可预测。
Spring 通过 org.springframework.core.Ordered
接口来解决这一问题:
public interface Ordered {
int getOrder();
}
在 miniSpring 中,我们同样让 AspectJExpressionPointcutAdvisor
实现一个 Ordered
接口:
public class AspectJExpressionPointcutAdvisor implements PointcutAdvisor, Ordered {
private String expression;
private Advice advice;
private int order = Integer.MAX_VALUE; // 默认优先级最低
@Override
public int getOrder() {
return this.order;
}
public void setOrder(int order) {
this.order = order;
}
}
真实spring在AbstractAdvisorAutoProxyCreator中对advisor进行了排序。
这里我们选择在具体代理类中从AdvisedSupport中获得advisor数组后在排序,并进行适配,见下:
2.4 具体排序实现与扩展更多通知类型:
这里需要修改一下advise的存储类型,之前写为PointcutAdvisor,为了支持排序,应该为AspectJExpressionPointcutAdvisor
。
package com.miniSpring.aop;
import com.miniSpring.aop.aspectj.AspectJExpressionPointcutAdvisor;
import java.util.ArrayList;
import java.util.List;
/**
* AdvisedSupport 是 AOP 代理配置的核心承载类,
* 用于保存目标对象、方法拦截器链和方法匹配器等信息。
*
* 主要职责:
* - 保存被代理的目标对象(TargetSource)
* - 保存方法拦截器链(List<MethodInterceptor>)
* - 保存方法匹配器(MethodMatcher),用于判断是否应用拦截器
*
* 这样设计方便代理生成时统一读取相关配置,
* 并支持多拦截器的链式调用,增强灵活性。
*/
public class AdvisedSupport {
/**
* 封装目标对象及其类型
*/
private TargetSource targetSource;
// 改成存 Advisor 列表,而非 MethodInterceptor 列表
private List<AspectJExpressionPointcutAdvisor> advisors = new ArrayList<AspectJExpressionPointcutAdvisor>();
/**
* 方法匹配器,判断某个方法是否需要被增强
*/
private MethodMatcher methodMatcher;
/*
默认false代表用JDK动态代理,true代表用Cglib。
*/
private boolean proxyTargetClass = false;
public boolean isProxyTargetClass() {
return proxyTargetClass;
}
public void setProxyTargetClass(boolean proxyTargetClass) {
this.proxyTargetClass = proxyTargetClass;
}
// ========== getter/setter ==========
public TargetSource getTargetSource() {
return targetSource;
}
public void setTargetSource(TargetSource targetSource) {
this.targetSource = targetSource;
}
public List<AspectJExpressionPointcutAdvisor> getAdvisors() {
return advisors;
}
public void setAdvisors(List<AspectJExpressionPointcutAdvisor> advisors) {
this.advisors = advisors;
}
public MethodMatcher getMethodMatcher() {
return methodMatcher;
}
public void setMethodMatcher(MethodMatcher methodMatcher) {
this.methodMatcher = methodMatcher;
}
// ========== 方便添加单个拦截器的辅助方法 ==========
/**
* 方便向拦截器链添加一个advisor
*/
public void addAdvisor(AspectJExpressionPointcutAdvisor advisor) {
this.advisors.add(advisor);
}
}
JdkDynamicAopProxy:
/**
* 基于 JDK 动态代理的 AOP 代理实现类。
* 通过实现 InvocationHandler 接口,实现对目标对象方法的拦截和增强。
*/
public class JdkDynamicAopProxy implements AopProxy, InvocationHandler {
/**
* 封装了被代理对象、方法匹配器和方法拦截器等信息的配置类
*/
private final AdvisedSupport advisedSupport;
/**
* 构造函数,传入被代理的配置信息
* @param advised 代理相关的配置,包括目标对象、方法匹配器、拦截器等
*/
public JdkDynamicAopProxy(AdvisedSupport advised) {
this.advisedSupport = advised;
}
/**
* 创建并返回目标对象的 JDK 动态代理对象
* @return 代理对象,类型为目标对象的接口类型
*/
@Override
public Object getProxy() {
// 使用当前线程上下文类加载器,目标类接口列表,以及当前对象(作为 InvocationHandler)
// 1. 获取目标对象的Class(如UserService.class)
Class<?> targetClass = advisedSupport.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(advisedSupport.getTargetSource().getTarget(), args);
}
// 2. 获取匹配的Advisor
List<AspectJExpressionPointcutAdvisor> eligibleAdvisors = new ArrayList<>();
for (AspectJExpressionPointcutAdvisor advisor : advisedSupport.getAdvisors()) {
if (advisor.getPointcut().getMethodMatcher()
.matches(method, advisedSupport.getTargetSource().getTarget().getClass())) {
eligibleAdvisors.add(advisor);
}
}
// 3. 对 Advisors 按 Order 排序
eligibleAdvisors.sort(Comparator.comparingInt(Ordered::getOrder));
// 4. 转换 Advisors → MethodInterceptors(使用适配器注册中心)
List<MethodInterceptor> interceptorChain = new ArrayList<>();
for (Advisor advisor : eligibleAdvisors) {
interceptorChain.addAll(adaptAdviceToInterceptor(advisor.getAdvice()));
}
// 4. 创建方法调用器,封装目标对象、方法、参数和拦截器链
ReflectiveMethodInvocation invocation = new ReflectiveMethodInvocation(
advisedSupport.getTargetSource().getTarget(),
method,
args,
interceptorChain
);
// 5. 执行拦截器链(责任链模式),最终调用目标方法
return invocation.proceed();
}
/**
* 把 Advice 转换成 MethodInterceptor 列表
* 模拟 Spring 的 AdvisorAdapterRegistry
*/
private List<MethodInterceptor> adaptAdviceToInterceptor(Advice advice) {
List<MethodInterceptor> interceptors = new ArrayList<>();
if (advice instanceof MethodAroundAdvice) {
interceptors.add(new MethodAroundAdviceInterceptor((MethodAroundAdvice) advice));
} else if (advice instanceof MethodBeforeAdvice) {
interceptors.add(new MethodBeforeAdviceInterceptor((MethodBeforeAdvice) advice));
} else if (advice instanceof MethodAfterAdvice) {
interceptors.add(new MethodAfterAdviceInterceptor((MethodAfterAdvice) advice));
} else if (advice instanceof MethodInterceptor) {
// 仅对已经实现了 MethodInterceptor 的 Advice 支持直接加入
interceptors.add((MethodInterceptor) advice);
} else {
throw new IllegalArgumentException("Unsupported advice type: " + advice.getClass());
}
return interceptors;
}
}
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());
// 传入当前 Cglib2AopProxy 实例,供内部类调用 adaptAdviceToInterceptor
enhancer.setCallback(new DynamicAdvisedInterceptor(advised, this));
return enhancer.create();
}
/**
* 将 Advice 转换成 MethodInterceptor 列表
*/
public List<org.aopalliance.intercept.MethodInterceptor> adaptAdviceToInterceptor(Advice advice) {
List<org.aopalliance.intercept.MethodInterceptor> interceptors = new ArrayList<>();
if (advice instanceof MethodAroundAdvice) {
interceptors.add(new MethodAroundAdviceInterceptor((MethodAroundAdvice) advice));
} else if (advice instanceof MethodBeforeAdvice) {
interceptors.add(new MethodBeforeAdviceInterceptor((MethodBeforeAdvice) advice));
} else if (advice instanceof MethodAfterAdvice) {
interceptors.add(new MethodAfterAdviceInterceptor((MethodAfterAdvice) advice));
} else if (advice instanceof org.aopalliance.intercept.MethodInterceptor) {
interceptors.add((org.aopalliance.intercept.MethodInterceptor) advice);
} else {
throw new IllegalArgumentException("Unsupported advice type: " + advice.getClass());
}
return interceptors;
}
/**
* CGLIB 的 MethodInterceptor
* 负责拦截目标对象的方法调用,执行拦截器链或直接调用目标方法
*/
private static class DynamicAdvisedInterceptor implements MethodInterceptor {
private final AdvisedSupport advised;
private final Cglib2AopProxy proxyInstance;
public DynamicAdvisedInterceptor(AdvisedSupport advised, Cglib2AopProxy proxyInstance) {
this.advised = advised;
this.proxyInstance = proxyInstance;
}
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
// 1. Object 类方法直接调用,不做增强
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. 对 Advisors 按 Order 排序
eligibleAdvisors.sort(Comparator.comparingInt(advisor -> ((Ordered) advisor).getOrder()));
// 4. 转换 Advisors → MethodInterceptors(通过外部 proxyInstance 调用)
List<org.aopalliance.intercept.MethodInterceptor> interceptorChain = new ArrayList<>();
for (Advisor advisor : eligibleAdvisors) {
interceptorChain.addAll(proxyInstance.adaptAdviceToInterceptor(advisor.getAdvice()));
}
// 5. 执行拦截器链,传入自定义 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) {
return methodProxy.invoke(target, arguments);
}
currentInterceptorIndex++;
org.aopalliance.intercept.MethodInterceptor interceptor = methodInterceptorList.get(currentInterceptorIndex);
return interceptor.invoke(this);
}
}
}
测试:
xml:
可以看到给每个AspectJExpressionPointcutAdvisor加上了order属性。
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean class="com.miniSpring.beans.factory.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:token.properties"/>
</bean>
<!-- 自动代理创建器:-->
<bean class="com.miniSpring.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
<!-- aop组合1-->
<bean id="beforeAdvice1" class="com.miniSpring.test.bean.LogBeforeAdvice"/>
<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"/>
<property name="order" value="3"/>
</bean>
<!-- aop组合2-->
<bean id="afterAdvice2" class="com.miniSpring.test.bean.LogAfterAdvice"/>
<bean id="methodInterceptor2" class="com.miniSpring.aop.adapter.MethodAfterAdviceInterceptor">
<property name="advice" ref="afterAdvice2"/>
</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"/>
<property name="order" value="2"/>
</bean>
<!-- aop组合3-->
<bean id="aroundAdvice3" class="com.miniSpring.test.bean.LogAroundAdvice"/>
<bean id="methodInterceptor3" class="com.miniSpring.aop.adapter.MethodAroundAdviceInterceptor">
<property name="advice" ref="aroundAdvice3"/>
</bean>
<bean id="pointcutAdvisor3" class="com.miniSpring.aop.aspectj.AspectJExpressionPointcutAdvisor">
<property name="expression" value="execution(* com.miniSpring.test.bean.IUserService.*(..))"/>
<property name="advice" ref="methodInterceptor3"/>
<property name="order" value="1"/>
</bean>
<component-scan base-package="com.miniSpring.test.bean"/>
</beans>
结果:
其他都不变,得到结果:
可以看到环绕通知先执行了,与明确排序的一样,而之前是前置通知先执行。
环绕通知: 方法 queryUserInfo 执行前
前置通知: 方法 queryUserInfo 即将执行
后置通知: 方法 queryUserInfo 执行完毕, 返回值: CMD137,北京,亦庄,123_TEST_TOKEN_321
环绕通知: 方法 queryUserInfo 执行后, 返回值: CMD137,北京,亦庄,123_TEST_TOKEN_321
测试结果:CMD137,北京,亦庄,123_TEST_TOKEN_321
Process finished with exit code 0
简单梳理整个aop系统:
实现一个aop具体组合:
1.创建一个AspectJExpressionPointcutAdvisor Bean, AspectJExpressionPointcutAdvisor内:
1.1 expression String:切入点表达式
1.2 advice MethodBeforeAdviceInterceptor(2.)(实现MethodInterceptor,MethodInterceptor实现advice): 具体的拦截方法实现。
1.3 order int:拦截链排序。
2.创建一个MethodBeforeAdviceInterceptor Bean:
2.1 advice 自定义方法,继承MethodBeforeAdvice/MethodAfterAdvice
3.自定义拦截方法,需要实现相对应的接口:
- MethodBeforeAdvice
- MethodAfterAdvice
- MethodAroundAdvice
aop生命周期:
在目标类bean的初始化完成后,DefaultAdvisorAutoProxyCreator
检查所有 Advisor(因为实现了postProcessAfterInitialization),如果有匹配的AspectJExpressionPointcutAdvisor,就会开启代理流程:
1.打包所有通过 Pointcut 匹配筛选出适用于当前 bean 的 Advisor通知器到advisedSupport中。
2.使用代理工厂开始创建代理对象:
3.在invoke方法中从advisedSupport中得到所有的Advisor,并按照order排序。
4.转换 Advisors → MethodInterceptors(使用适配器注册中心)
5.创建方法调用器ReflectiveMethodInvocation,封装目标对象、方法、参数和拦截器链,让代理类存储对原始方法的引用以及AdvisedSupport对象,这个代理逻辑的 “元数据容器”。
6.返回被代理的对象。
7.调用目标方法 invoke () :
7.1:代理对象会创建一个ReflectiveMethodInvocation
对象,它封装了:
目标对象(原始对象)
要执行的方法(doSomething()
)
方法参数
拦截器链(包含BeforeAdvice
和AfterAdvice
对应的拦截器)
7.2 : 直接调用这个ReflectiveMethodInvocation
对象的proceed()
方法启动整个执行流程。