Spring代理与责任链

321 阅读2分钟

前言

前面我们已经讲到了singletonFactories的作用和在初始化后增强的一个阶段中会将bean变成一个代理bean,创建代理bean的流程中会看到如下源码:

image-20220111101236853.png 所以spring中创建代理对象有两种方式:Cglib和JdkDynamic,使用代码示例来感受下这两种方式是如何创建代理和调用接口的

Jdk代理

只能对接口进行代理(newProxyInstance的第二个参数决定),生成一个接口的匿名类,匿名类拥有InvocationHandler的引用,Jdk动态代理只是想在调用目标类的方法前再加一层逻辑。至理名言:没有什么是加入一层解决不了的

public class JdkProxy {
    static class ProxyHandler implements InvocationHandler {
        private Object targetObject;
        public ProxyHandler(Object targetObject) {
            this.targetObject = targetObject;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("这里有个切面");
            return method.invoke(targetObject,args);
        }
    }
    public static final Object createProxy(Object targetObject) {
        return Proxy.newProxyInstance(JdkProxy.class.getClassLoader(), targetObject.getClass().getInterfaces(), new ProxyHandler(targetObject));
    }
    public static void main(String[] args) {
        User userA = (User)JdkProxy.createProxy(new UserA());
        userA.f1();
        User userB = (User)JdkProxy.createProxy(new UserB());
        userB.f1();
    }
}

运行结果与上一篇文章中使用切面的效果相同,createProxy为目标类的所有接口实现一个匿名类,且匿名类的实例拥有InvocationHandler对应的实例。通过反射在调用匿名类的任何接口时都会进入invoke方法,使得目标类的方法被调用前都能被拦截,并加入一层逻辑

Cglib代理

能对接口和类进行代理,生成代理的子类,生成的子类拥有MethodInterceptor的引用,通过反射调用任何接口时都会进入intercept方法,使得目标类的方法被调用前都能被拦截,并加入一层逻辑

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
​
import java.lang.reflect.Method;
​
public class CglibProxy {
    static class ProxyHandler implements MethodInterceptor {
        private Object targetObject;
        public ProxyHandler(Object targetObject) {
            this.targetObject = targetObject;
        }
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            System.out.println("这里有个切面");
            return method.invoke(targetObject,objects);
        }
    }
    public static final Object createProxy(Object targetObject) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(targetObject.getClass());
        enhancer.setCallback(new ProxyHandler(targetObject));
        return enhancer.create();
    }
    public static void main(String[] args) {
        User userA = (User) CglibProxy.createProxy(new UserA());
        userA.f1();
        User userB = (User) CglibProxy.createProxy(new UserB());
        userB.f1();
    }
}

责任链模式

上面讲的代理与Spring Aop有很强的关联,在学习Aop之前先温习一下责任链模式。责任链模式在spring中有广泛的应用,http请求过滤、spring security权限过滤、aop切面顺序调用等都会涉及

责任链模式:

image-20220112112939337.png 示例代码:

public interface MethodAdvice {
    Object proceed(MethodInterceptorChain chain) throws Throwable;
}
public class MethodInterceptorChain{
    //拥有拦截器链条
    List<MethodAdvice> chains = new ArrayList<>();
    private TargetMethod targetMethod;
    int index = 0;
    public void addInterceptor(MethodAdvice method){
        chains.add(method);
    }
    public Object proceed() throws Throwable {
        if(index == chains.size()){
            return targetMethod.method.invoke(targetMethod.targetObject,targetMethod.args);
        }else{
            //顶层遍历拦截器
            return chains.get(index++).proceed(this);
        }
    }
    static class TargetMethod{
        private Object targetObject;
        private Method method;
        private Object[] args;
    }
    static class ProxyHandler implements MethodInterceptor {
        private Object targetObject;
        private MethodInterceptorChain chain;
        public ProxyHandler(Object targetObject,MethodInterceptorChain chain) {
            this.targetObject = targetObject;
            this.chain = chain;
        }
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            TargetMethod targetMethod = new TargetMethod();
            targetMethod.method = method;
            targetMethod.targetObject = this.targetObject;
            targetMethod.args = objects;
            this.chain.targetMethod = targetMethod;
            //链条调用触发
            return this.chain.proceed();
        }
    }
    public  Object createProxy(Object targetObject) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(targetObject.getClass());
        enhancer.setCallback(new ProxyHandler(targetObject,this));
        return enhancer.create();
    }
    public static void main(String[] args) {
        MethodInterceptorChain chain = new MethodInterceptorChain();
        User userA = (User) chain.createProxy(new UserA());
        chain.addInterceptor(chain1 -> {
            System.out.println("around 之前");
            Object ret = chain1.proceed();
            System.out.println("around 之后");
            return ret;
        });
        chain.addInterceptor((chain1 -> {
            System.out.println("before...");
            return chain1.proceed();
        }));
        chain.addInterceptor(chain1 -> {
            Object ret = null;
            try {
                ret = chain1.proceed();
            } finally {
                System.out.println("after...");
            }
            return ret;
        });
        chain.addInterceptor(chain1 -> {
            Object ret = chain1.proceed();
            System.out.println("afterReturning...");
            return ret;
        });
        chain.addInterceptor(chain1 -> {
            Object ret = null;
            try {
                ret = chain1.proceed();
            } catch (Throwable e) {
                System.out.println("afterThrowing...");
            }
            return ret;
        });
        userA.f1();
    }
}

运行效果

image-20220111184404242.png

可以看出与Aop中几个注解的顺序是一致的