代码地址
spring04
觉得博主还可以给个Star
在我们看五个通知执行源码之前,我们先来了解一下核心问题。SpringAop核心的设计模式为,动态代理模式和责任链设计模式。动态代理前面也提到过,cglib和jdk代理。至于责任链模式才是这一次的重点内容。他关系到我们五个通知为什么会有序的执行。
项目结构:
我们先来模拟一下责任链模式,责任链设计模式核心是递归的思路,但是递归会产生溢出的现象,所以我们需要约束条件,使程序正常运行.在以下程序中,除了更改前置和环绕通知的添加顺序之外,其他的方式均不会导致结果的变化.
此模拟不是完整的AOP五个通知正常顺序模拟,针对于环绕通知为何出现在第一个,可以查看AspectJAwareAdvisorAutoProxyCreator的sortAdvisors方法,在获取到增强之后,内部进行了一个排序
对于为何"环绕通知之后"位置不正确,是因为它的内部进行了一定的变化,和其他几个通知有出入.我们下次进行详细的解读.
AfterInterceptor.java
package com.interceptor.impl;
import com.interceptor.MethodInterceptor;
import com.invocation.MethodInvocation;
import java.lang.reflect.InvocationTargetException;
public class AfterInterceptor implements MethodInterceptor {
@Override
public void invoke(MethodInvocation methodInvocation) throws InvocationTargetException, IllegalAccessException {
methodInvocation.process();
System.out.println("后置通知");
}
}
AroundInterceptor.java
package com.interceptor.impl;
import com.interceptor.MethodInterceptor;
import com.invocation.MethodInvocation;
import java.lang.reflect.InvocationTargetException;
public class AroundInterceptor implements MethodInterceptor {
@Override
public void invoke(MethodInvocation methodInvocation) throws InvocationTargetException, IllegalAccessException {
System.out.println("环绕通知之前");
methodInvocation.process();
System.out.println("环绕通知之后");
}
}
BeforeInterceptor.java
package com.interceptor.impl;
import com.interceptor.MethodInterceptor;
import com.invocation.MethodInvocation;
import java.lang.reflect.InvocationTargetException;
public class BeforeInterceptor implements MethodInterceptor {
@Override
public void invoke(MethodInvocation methodInvocation) throws InvocationTargetException, IllegalAccessException {
// methodInvocation.process();
System.out.println("前置通知");
methodInvocation.process();
}
}
MethodInterceptor.java
package com.interceptor;
import com.invocation.MethodInvocation;
import java.lang.reflect.InvocationTargetException;
public interface MethodInterceptor {
/**
* 通知共用接口
*/
public void invoke(MethodInvocation methodInvocation) throws InvocationTargetException, IllegalAccessException;
}
DefaultMethodInvocation.java
package com.invocation.impl;
import com.interceptor.MethodInterceptor;
import com.invocation.MethodInvocation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
public class DefaultMethodInvocation implements MethodInvocation {
ArrayList<MethodInterceptor> methodInterceptorArrayList;
static int index;
Method method;
Object object;
public DefaultMethodInvocation(ArrayList<MethodInterceptor> methodInterceptorArrayList, Method method, Object object) {
this.methodInterceptorArrayList = methodInterceptorArrayList;
this.method = method;
this.object = object;
}
public DefaultMethodInvocation(ArrayList<MethodInterceptor> methodInterceptorArrayList) {
this.methodInterceptorArrayList = methodInterceptorArrayList;
}
@Override
public void process() throws InvocationTargetException, IllegalAccessException {
if(index == methodInterceptorArrayList.size()){
//执行目标方法
method.invoke(object);
return;
}
//调用添加进去的通知
MethodInterceptor methodInterceptor = methodInterceptorArrayList.get(index);
index++;
methodInterceptor.invoke(this);
//递归循环调用
// process(this);
}
}
MethodInvocation.java
package com.invocation;
import com.interceptor.MethodInterceptor;
import java.lang.reflect.InvocationTargetException;
public interface MethodInvocation {
/**
* 调用链的形成
*/
void process() throws InvocationTargetException, IllegalAccessException;
}
UserService.java
package com.service;
public class UserService {
public void add(){
System.out.println("addUserService");
}
}
Application.java
package com;
import com.interceptor.MethodInterceptor;
import com.interceptor.impl.AfterInterceptor;
import com.interceptor.impl.AroundInterceptor;
import com.interceptor.impl.BeforeInterceptor;
import com.invocation.impl.DefaultMethodInvocation;
import com.service.UserService;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
public class Application {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
ArrayList<MethodInterceptor> methodInterceptorList = new ArrayList<>();
methodInterceptorList.add(new AroundInterceptor());
methodInterceptorList.add(new BeforeInterceptor());
// methodInterceptorList.add(new AroundInterceptor());
methodInterceptorList.add(new AfterInterceptor());
UserService userService = new UserService();
Method loginMethod = UserService.class.getMethod("add");
new DefaultMethodInvocation(methodInterceptorList,loginMethod,userService).process();
}
}