静态通知调用
静态通知调用
目录
- 适配器模式:不同通知统一转换为环绕通知
- 无参数绑定通知链执行过程,责任链模式体现
- 模拟实现MethodInvocation
适配器模式
上一章的Main方法里面创建Advisors方法可以抽象为以下几个方法,分别对应不同的AspectJMethodxxxxAdvice
,然后将不同通知统一转化为环绕通知MethodInterceptor。
// 切面实例工厂
AspectInstanceFactory factory = new SingletonAspectInstanceFactory(new A18Aspect());
// 1. 获取相关通知
List<Advisor> beforeAdvisors = getBeforeAdvisors(factory);
List<Advisor> afterAdvisors = getAfterAdvisors(factory);
// 2. 将相关通知统一转化为环绕通知MethodInterceptor
A18Target target = new A18Target();
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(target);
proxyFactory.addAdvisors(beforeAdvisors);
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
List<Object> methodInterceptors = proxyFactory.getInterceptorsAndDynamicInterceptionAdvice(A18Target.class.getMethod("foo"), A18Target.class);
for (Object methodInterceptor : methodInterceptors) {
System.out.println(methodInterceptor);
}
为什么要转化
无论是ProxyFactory基于哪种方式创建代理,最后都要调用advice的都是MethodInvocation
对象:
a. 因为Advisor有多个,且一个套一个调用,因此需要一个调用链对象,即MethodInvocation
b. MethodInvocation 要知道advice有哪些,还要知道目标,调用次序如下:
before1 -> before2 -> target -> after2 -> after1
c. 从上图可以看出,环绕通知才适合作为advice,因此其他before,afterReturning,afterThrowing都会被转化为环绕通知
d. 统一转换为环绕通知,提现的是设计模式中的适配器模式
- 对外是为了方便要区分before、afterReturing、afterThrowing
- 对内都是使用环绕通知,统一使用MethodInterceptor表示
什么是适配器模式
以切面静态转换场景为例,通知会被转换为MethodInterceptor
,而@Before
这一类注解会被解析为AspectJMethodBeforeAdvice形式这样的另外一套接口。因此注解解析后的接口是不能直接使用的,我们需要把他统一转换为MethodInterceptor,而中间转换的类对象称之为适配器对象。
org.springframework.aop.framework.adapter.AdvisorAdapter:
- MethodBeforeAdviceAdapter 将 @Before 的 AspectJMethodBeforeAdvice 适配为 MethodBeforeAdviceInterceptor
- AfterReturningAdviceAdapter 将 @AfterReturning AspectJAfterReturningAdvice 适配为 AfterReturningAdviceInterceptor
获取适配器的方式为:
// 2. 将相关通知统一转化为环绕通知MethodInterceptor
A18Target target = new A18Target();
ProxyFactory proxyFactory = new ProxyFactory();
// 准备把 MethodInvocation 放入通过advice的形式当前线程。(放在最外层)
proxyFactory.addAdvice(0,ExposeInvocationInterceptor.INSTANCE);
proxyFactory.setTarget(target);
proxyFactory.addAdvisors(beforeAdvisors);
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
List<Object> methodInterceptors = proxyFactory.getInterceptorsAndDynamicInterceptionAdvice(A18Target.class.getMethod("foo"), A18Target.class);
for (Object methodInterceptor : methodInterceptors) {
System.out.println(methodInterceptor);
}
// 通过ProxyFactory.getInterceptorsAndDynamicInterceptionAdvice将相关通知统一转化为环绕通知MethodInterceptor
A18Target target = new A18Target();
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(target);
proxyFactory.addAdvisors(beforeAdvisors);
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
List<Object> methodInterceptors = proxyFactory.getInterceptorsAndDynamicInterceptionAdvice(A18Target.class.getMethod("foo"), A18Target.class);
for (Object methodInterceptor : methodInterceptors) {
System.out.println(methodInterceptor);
}
调用链执行
// 3. 创建执行调用链(组成:环绕通知s + 目标信息)
// 3.1 准备调用链(package org.springframework.aop.framework;)
MethodInvocation methodInvocation = new ReflectiveMethodInvocation(
null,
target,
A18Target.class.getMethod("foo"),
new Object[0],
A18Target.class,
methodInterceptors
);
// 3.2 调用调用链
methodInvocation.proceed();
实现责任链模式:
public class A18_1 {
static class A18_1Aspect {
@Before("execution(* foo()) ")
public void before() {
System.out.println("before1");
}
@Before("execution (* foo())")
public void before2() {
System.out.println("before2");
}
public void after() {
System.out.println("after");
}
public void afterReturning() {
System.out.println("afterReturning");
}
}
static class A18_1Target {
public void foo() {
System.out.println("target.foo");
}
}
static class A18_1Advice1 implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("Advice1 before()");
Object proceed = invocation.proceed();
System.out.println("Advice1 after()");
return proceed;
}
}
static class A18_1Advice2 implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("Advice2 before()");
Object proceed = invocation.proceed();
System.out.println("Advice2 after()");
return proceed;
}
}
/**
* 1. 把必要信息存储在 invocation 中:target、
* 2.
*/
static class MyInvocation implements MethodInvocation {
// 目标对象
private Object target;
// 目标方法
private Method method;
// 目标方法的参数
private Object[] params;
// 环绕通知的list
private List<MethodInterceptor> methodInterceptorList;
private int curInterceptorIndex = -1;
public MyInvocation(Object target, Method method, Object[] params, List<MethodInterceptor> methodInterceptorList) {
this.target = target;
this.method = method;
this.params = params;
this.methodInterceptorList = methodInterceptorList;
}
@Override
public Method getMethod() {
return method;
}
@Override
public Object[] getArguments() {
return params;
}
@Override
public Object proceed() throws Throwable {
// 调用每一个环绕通知 和 目标
if (curInterceptorIndex == methodInterceptorList.size() - 1) {
return method.invoke(target, params);
}
MethodInterceptor curMethodInterceptor = methodInterceptorList.get(++this.curInterceptorIndex);
return curMethodInterceptor.invoke(this);
}
@Override
public Object getThis() {
// 返回目标对象
return target;
}
@Override
public AccessibleObject getStaticPart() {
// todo
return method;
}
}
public static void main(String[] args) throws Throwable {
A18_1Target target = new A18_1Target();
A18_1Advice1 advice1 = new A18_1Advice1();
A18_1Advice2 advice2 = new A18_1Advice2();
List<MethodInterceptor> methodInterceptors = Lists.newArrayList(advice2, advice1);
ProxyFactory factory = new ProxyFactory();
factory.setTarget(target);
MyInvocation invocation = new MyInvocation(
target,
A18_1Target.class.getMethod("foo"),
new Object[0],
methodInterceptors
);
invocation.proceed();
}
}