关关雎鸠, 在河之洲. 窈窕淑女, 君子好逑.
https://user-gold-cdn.xitu.io/2019/2/19/1690484302c4d39c?w=1920&h=1280&f=jpeg&s=268488
概述
AOP(Aspect Orient Programming), 我们一般称为面向方面 (切面) 编程, 作为面向对象的一种补充, 用于处理系统中分布于各个模块的横切关注点, 比如事务管理, 日志, 缓存等等. Spring AOP 采用的是动态代理, 在运行期间对业务方法进行增强, 所以不会生成新类, Spring AOP 提供了对 JDK 动态代理的支持以及 CGLib 的支持. 本章我们不关注 aop 代理类的实现, 我简单实现一个指定次序的链式调用.
实现链式调用的
MethodInterceptor 定义拦截器链, MethodInvocation 递归进入下一个拦截器链中. 类图如下:
- https://user-gold-cdn.xitu.io/2019/2/19/1690484302ab3847?w=2208&h=677&f=png&s=70538
- MethodInterceptor
- public interface MethodInterceptor {
- Object invoke(MethodInvocation invocation) throws Throwable;
- }
- MethodInvocation
- public interface MethodInvocation {
- Object proceed() throws Throwable;
- }
AbstractAspectJAdvice
抽象类, 实现 MethodInterceptor
- public abstract class AbstractAspectJAdvice implements MethodInterceptor{
- private Method adviceMethod;
- private Object adviceObject;
- public AbstractAspectJAdvice(Method adviceMethod, Object adviceObject) {
- this.adviceMethod = adviceMethod;
- this.adviceObject = adviceObject;
- }
- public Method getAdviceMethod() {
- return this.adviceMethod;
- }
- public void invokeAdviceMethod() throws Throwable {
- adviceMethod.invoke(adviceObject);
- }
- }
AspectJBeforeAdvice
前置通知
- public class AspectJBeforeAdvice extends AbstractAspectJAdvice {
- public AspectJBeforeAdvice(Method method, Object adviceObject) {
- super(method, adviceObject);
- }
- @Override
- public Object invoke(MethodInvocation invocation) throws Throwable{
- this.invokeAdviceMethod();
- Object o = invocation.proceed();
- return o;
- }
- }
AspectJAfterReturningAdvice
后置通知
- public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice {
- public AspectJAfterReturningAdvice(Method method, Object adviceObject) {
- super(method, adviceObject);
- }
- @Override
- public Object invoke(MethodInvocation invocation) throws Throwable{
- Object o = invocation.proceed();
- this.invokeAdviceMethod();
- return o;
- }
- }
ReflectiveMethodInvocation
实现 MethodInvocation,proceed()方法递归实现链式调用.
- public class ReflectiveMethodInvocation implements MethodInvocation {
- private final Object targetObject;
- private final Method targetMethod;
- private final List<MethodInterceptor> interceptorList;
- private int currentInterceptorIndex = -1;
- public ReflectiveMethodInvocation(Object targetObject, Method targetMethod, List<MethodInterceptor> interceptorList) {
- this.targetObject = targetObject;
- this.targetMethod = targetMethod;
- this.interceptorList = interceptorList;
- }
- @Override
- public Object proceed() throws Throwable {
- if (this.currentInterceptorIndex == this.interceptorList.size() - 1) {
- return invokeJoinPoint();
- }
- this.currentInterceptorIndex++;
- MethodInterceptor interceptor =
- this.interceptorList.get(this.currentInterceptorIndex);
- return interceptor.invoke(this);
- }
- private Object invokeJoinPoint() throws Throwable {
- return this.targetMethod.invoke(this.targetObject);
- }
- }
NioCoderService
模拟 service 类
- public class NioCoderService {
- public void testAop() {
- System.out.println("http://niocoder.com/");
- }
- }
TransactionManager
模拟通知类
- public class TransactionManager {
- public void start() {
- System.out.println("start tx");
- }
- public void commit() {
- System.out.println("commit tx");
- }
- public void rollback() {
- System.out.println("rollback tx");
- }
- }
- ReflectiveMethodInvocationTest
- beforeAdvice->afterReturningAdvice
测试类, 测试通知
- public class ReflectiveMethodInvocationTest {
- private AspectJBeforeAdvice beforeAdvice = null;
- private AspectJAfterReturningAdvice afterReturningAdvice = null;
- private NioCoderService nioCoderService;
- private TransactionManager tx;
- public void setUp() throws Exception {
- nioCoderService = new NioCoderService();
- tx = new TransactionManager();
- beforeAdvice = new AspectJBeforeAdvice(TransactionManager.class.getMethod("start"), tx);
- afterReturningAdvice = new AspectJAfterReturningAdvice(TransactionManager.class.getMethod("commit"), tx);
- }
- public void testMethodInvocation() throws Throwable {
- Method method = NioCoderService.class.getMethod("testAop");
- List<MethodInterceptor> interceptorList = new ArrayList<>();
- interceptorList.add(beforeAdvice);
- interceptorList.add(afterReturningAdvice);
- ReflectiveMethodInvocation mi = new ReflectiveMethodInvocation(nioCoderService, method, interceptorList);
- mi.proceed();
- }
- public static void main(String[] args) throws Throwable {
- ReflectiveMethodInvocationTest reflectiveMethodInvocationTest = new ReflectiveMethodInvocationTest();
- reflectiveMethodInvocationTest.setUp();
- reflectiveMethodInvocationTest.testMethodInvocation();
- }
- }
输出:
- start tx
- http://niocoder.com/
- commit tx
时序图 beforeAdvice->afterReturningAdvice
https://user-gold-cdn.xitu.io/2019/2/19/16904843029513d0?w=2586&h=2021&f=png&s=128819
- https://user-gold-cdn.xitu.io/2019/2/19/1690484302f456e8?w=1710&h=842&f=png&s=66348
- afterReturningAdvice->beforeAdvice
修改 interceptorList 的顺序
- public void testMethodInvocation() throws Throwable {
- Method method = NioCoderService.class.getMethod("testAop");
- List<MethodInterceptor> interceptorList = new ArrayList<>();
- interceptorList.add(afterReturningAdvice);
- interceptorList.add(beforeAdvice);
- ReflectiveMethodInvocation mi = new ReflectiveMethodInvocation(nioCoderService, method, interceptorList);
- mi.proceed();
- }
输出:
- start tx
- http://niocoder.com/
- commit tx
时序图 afterReturningAdvice->beforeAdvice
https://user-gold-cdn.xitu.io/2019/2/19/1690484302fbb1c2?w=2586&h=2024&f=png&s=94158
https://user-gold-cdn.xitu.io/2019/2/19/169048430309ea9f?w=1857&h=865&f=png&s=62840
代码下载
GitHub:
代码下载
GitHub:
来源: https://juejin.im/post/5c6ba6eff265da2dbf5efd66