前言
-
这个系列主要讲优秀的开源框架对于责任链这个设计模式的运用,对于好的设计,我们关键是学习他的思想并运用在我们的编码中。
-
这个系列的所有代码都是我根据源码提炼之后的代码,不依赖原项目或框架,可以直接跑。
-
我不会讲每个具体是如何实现的,如果你觉得光看代码比较吃力,那么可以将代码复制下来,自己多运行几遍,我相信你一定能掌握,所以主打一个动手能力。
-
欢迎访问我的个人网站,里面有超多开源组件和项目,另外还有付费项目和博客,地址:https://openbytecode.com/
-
前两个小节主要介绍了 Tomcat 的 Filter 设计 和 SpringMVC 的 Interceptor 设计,本小节主要讲 Spring 中 AOP 的拦截器设计。
-
本系列 Github 地址:https://github.com/lijunping365/Open-Design
Spring 之 AOP 拦截器
public interface MethodInvocation {
/**
* Proceed to the next interceptor in the chain.
* <p>The implementation and the semantics of this method depends
* on the actual joinpoint type (see the children interfaces).
* @return see the children interfaces' proceed definition
* @throws Throwable if the joinpoint throws an exception
*/
Object proceed() throws Throwable;
/**
* Get the method being called.
* <p>This method is a friendly implementation of the
* {@link Joinpoint#getStaticPart()} method (same result).
* @return the method being called
*/
Method getMethod();
/**
* Get the arguments as an array object.
* It is possible to change element values within this
* array to change the arguments.
* @return the argument of the invocation
*/
Object[] getArguments();
/**
* Return the object that holds the current joinpoint's static part.
* <p>For instance, the target object for an invocation.
* @return the object (can be null if the accessible object is static)
*/
Object getThis();
}
public class BaseMethodInvocation implements MethodInvocation{
protected Object[] arguments;
protected final Object proxy;
protected final Object target;
protected final Method method;
protected final Class<?> targetClass;
protected final List<?> interceptors;
/**
* Index from 0 of the current interceptor we're invoking.
* -1 until we invoke: then the current interceptor.
*/
private int currentInterceptorIndex = -1;
protected BaseMethodInvocation(Object proxy,
Object target,
Method method,
Object[] arguments,
Class<?> targetClass,
List<?> interceptors) {
this.proxy = proxy;
this.target = target;
this.method = BridgeMethodResolver.findBridgedMethod(method);
this.arguments = adaptArgumentsIfNecessary(method, arguments);
this.targetClass = targetClass;
this.interceptors = interceptors;
}
@Override
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
if (this.currentInterceptorIndex == this.interceptors.size() - 1) {
return invoke();
}
Object interceptor = this.interceptors.get(++this.currentInterceptorIndex);
return ((MethodInterceptor) interceptor).invoke(this);
}
@Override
public Method getMethod() {
return this.method;
}
@Override
public Object[] getArguments() {
return this.arguments;
}
@Override
public Object getThis() {
return this.target;
}
/**
* Invoke the joinpoint using reflection.
* Subclasses can override this to use custom invocation.
* @return the return value of the joinpoint
* @throws Throwable if invoking the joinpoint resulted in an exception
*/
@Nullable
protected Object invoke() throws Throwable {
return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
}
/**
* @since 4.2.3
*/
static Object[] adaptArgumentsIfNecessary(Method method, @Nullable Object[] arguments) {
//...
return arguments;
}
}
public class IMethodInvocation extends BaseMethodInvocation{
private final MethodProxy methodProxy;
public IMethodInvocation(Object proxy,
Object target,
Method method,
Object[] arguments,
Class<?> targetClass,
List<?> interceptors,
MethodProxy methodProxy) {
super(proxy, target, method, arguments, targetClass, interceptors);
// Only use method proxy for public methods not derived from java.lang.Object
this.methodProxy = (Modifier.isPublic(method.getModifiers()) &&
method.getDeclaringClass() != Object.class && !AopUtils.isEqualsMethod(method) &&
!AopUtils.isHashCodeMethod(method) && !AopUtils.isToStringMethod(method) ?
methodProxy : null);
}
@Override
public Object proceed() throws Throwable {
return super.proceed();
}
@Override
protected Object invoke() throws Throwable {
if (this.methodProxy != null) {
return this.methodProxy.invoke(this.target, this.arguments);
}
else {
return super.invoke();
}
}
}
@FunctionalInterface
public interface MethodInterceptor {
/**
* Implement this method to perform extra treatments before and
* after the invocation. Polite implementations would certainly
* like to invoke {@link Joinpoint#proceed()}.
* @param invocation the method invocation joinpoint
* @return the result of the call to {@link Joinpoint#proceed()};
* might be intercepted by the interceptor
* @throws Throwable if the interceptors or the target object
* throws an exception
*/
Object invoke(MethodInvocation invocation) throws Throwable;
}
测试
/**
* 注意这里是实现我们自己的 MethodInterceptor
*
* @author lijunping on 2022/11/8
*/
public class FirstMethodInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("FirstMethodInterceptor .......Before");
Object proceed = invocation.proceed();// 调用 IMethodInvocation 的 proceed 方法,形成递归调用
System.out.println("FirstMethodInterceptor .......After");
return proceed;
}
}
/**
* 注意这里是实现我们自己的 MethodInterceptor
*
* @author lijunping on 2022/11/8
*/
public class SecondMethodInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("SecondMethodInterceptor .......Before");
Object proceed = invocation.proceed();// 调用 IMethodInvocation 的 proceed 方法,形成递归调用
System.out.println("SecondMethodInterceptor .......After");
return proceed;
}
}
public class DemoService {
public String test(){
System.out.println("tttttttttttttttttttt");
return "hello";
}
}
/**
* 注意这里的 MethodInterceptor 是 net.sf.cglib.proxy.MethodInterceptor
*
* @author lijunping on 2022/11/8
*/
public class DemoMethodInterceptor implements MethodInterceptor {
private final Object target;
private final List<?> chain;
public DemoMethodInterceptor(Object target, List<Object> chain) {
this.target = target;
this.chain = chain;
}
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
// 构建调用链
IMethodInvocation invocation = new IMethodInvocation(proxy, target, method, args, target.getClass(), chain, methodProxy);
// 执行调用链
return invocation.proceed();
}
}
public class ProxyFactory {
/**
* 实例化动态代理对象
* @param tClass 代理目标对象类型
* @param <T> 代理目标对象类型泛型
* @return 动态代理对象
*/
public static <T> T getProxyInstance(Class<T> tClass, MethodInterceptor interceptor) {
return getProxyInstance(tClass, tClass, interceptor);
}
/**
* 实例化动态代理对象,并转换为对应接口类型
* @param tClass 代理目标对象类型
* @param interfaceClass 代理目标对象接口类型
* @param <T> 代理目标对象接口类型泛型
* @return 动态代理对象
*/
public static <T> T getProxyInstance(Class<? extends T> tClass, Class<T> interfaceClass, MethodInterceptor interceptor) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(tClass);
enhancer.setClassLoader(tClass.getClassLoader());
enhancer.setCallback(interceptor); // 实现了 MethodInterceptor 接口的类
return interfaceClass.cast(enhancer.create());
}
}
public class ChainDemo {
public static void main(String[] args) {
// 创建目标对象
DemoService demoService = new DemoService();
// 构建拦截器链
List<Object> chain = new ArrayList<>();
chain.add(new FirstMethodInterceptor());
chain.add(new SecondMethodInterceptor());
// 创建 cglib 动态代理的 Interceptor
DemoMethodInterceptor interceptor = new DemoMethodInterceptor(demoService, chain);
// 获取代理对象
DemoService proxyInstance = ProxyFactory.getProxyInstance(DemoService.class, interceptor);
// 执行代理对象
proxyInstance.test();
}
}
输出结果:
FirstMethodInterceptor .......Before
SecondMethodInterceptor .......Before
tttttttttttttttttttt
SecondMethodInterceptor .......After
FirstMethodInterceptor .......After
欢迎在评论区留下你的总结