系列文章目录
SpringAOP实现
深入SpringAOP实现流程(源码分析)
使用递归算法+责任链模拟AOP底层通知调用
文章目录
- 系列文章目录
- 一、AOP通知
- 二、模拟AOP通知
- 1、包结构
- 2、interceptor
- 3、invocation
- 4、service
- 5、Test
- 6、运行结果
一、AOP通知
我们可以先看一个切面类
@Component
@Aspect//定义切面类
@EnableAspectJAutoProxy //开启AOP]
public class LogAOP {
@Pointcut("execution(* com.spring.aop.service..*.*(..))")
public void logAop() {
}
//前置通知
/**
* 方法执行前进行通知
*/
@Before("logAop()")
public void before() {
System.out.println("【前置通知】");
}
//后置通知
/**
* 方法体执行完通知
*/
@After("logAop()")
public void after() {
System.out.println("【后置通知】");
}
//运行通知
/**
* 运行通知和后置通知区别:
* 后置执行完了再去进行运行通知
* 当程序运行时有异常是不会去执行运行通知但是会执行后置通知
*/
@AfterReturning("logAop()")
public void AfterReturning() {
System.out.println("【运行通知】");
}
//异常通知
/**
* 出现异常了就会进行通知
*/
@AfterThrowing("logAop()")
public void AfterThrowing() {
System.out.println("【异常通知】");
}
//环绕通知
@Around("logAop()")
public void Around(ProceedingJoinPoint joinPoint) {
try {
System.out.println("【环绕通知】");//在方法之前执行
joinPoint.proceed();
System.out.println("【环绕通知】");//在方法之后执行
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
}
以上切面类中就体现了我们AOP的所有通知,那么这些通知在低层中如何调用的呢?我们先看一下通知结果然后我们再去手写模拟底层的一个通知
【环绕通知】
【前置通知】
【testMethod】
【环绕通知】
【后置通知】
【运行通知】
二、模拟AOP通知
1、包结构
- interceptor 是模拟通知的放的各种通知的共同方法和不同实现
- invocation 是模拟拼接调用链璐
- service 是模拟我们拦截的方法
- Test是测试类
2、interceptor
MethodInterceptor接口
public interface MethodInterceptor {
/**
* 定义共同通知的骨架
*/
void invoke(MethodInvocation methodInvocation);
}
前置通知实现
public class BeforeMethodInterceptor implements MethodInterceptor {
@Override
public void invoke(MethodInvocation methodInvocation) {
System.out.println("【前置通知】");
methodInvocation.process();
}
//前置通知完成了执行目标方法
}
后置通知实现
public class AfterMethodInterceptor implements MethodInterceptor {
@Override
public void invoke(MethodInvocation methodInvocation) {
//执行前置通知
methodInvocation.process();
System.out.println("【后置通知】");
}
}
环绕通知实现
public class AroundMethodInterceptor implements MethodInterceptor {
@Override
public void invoke(MethodInvocation methodInvocation) {
System.out.println("【目标方法之前环绕通知】");
//执行前置通知
methodInvocation.process();
System.out.println("【目标方法之后环绕通知】");
}
}
3、invocation
MethodInvocation接口
public interface MethodInvocation {
void process();
}
MethodInvocation实现类
public class DefaultMethodInvocation implements MethodInvocation {
/**
* 存放所有通知
*/
private List<MethodInterceptor> list;
private Object target;//目标对象
private Method method;//目标方法
private Object args[];//目标参数
//最终使用反射机制去执行方法
private int index;
public DefaultMethodInvocation(List<MethodInterceptor> list, Object target, Method method, Object[] args) {
this.list = list;
this.target = target;
this.method = method;
this.args = args;
}
/**
* 建立调用链路
*/
@Override
public void process() {
if (index == list.size()) {
try {
method.invoke(target, args); //执行目标方法
return;
} catch (Exception e) {
e.printStackTrace();
System.out.println("【出现异常】");
}
}
MethodInterceptor methodInterceptor = list.get(index++);
methodInterceptor.invoke(this);
}
}
4、service
public class TestService {
public void test(String userName) {
System.out.println("userName:" + userName);
}
}
5、Test
public class Test {
public static void main(String[] args) throws NoSuchMethodException {
//1、装配通知
List<MethodInterceptor> list = new ArrayList();
list.add(new BeforeMethodInterceptor());
list.add(new AfterMethodInterceptor());
list.add(new AroundMethodInterceptor());
//2、创建目标方法;
TestService testService = new TestService();
Method test = TestService.class.getMethod("test", String.class);
Object[] params = {"瑞文"};
new DefaultMethodInvocation(list, testService, test, params).process();
}
}
6、运行结果
【前置通知】
【目标方法之前环绕通知】
测试方法
【目标方法之后环绕通知】
【后置通知】