美文网首页
Java与Spring的代理

Java与Spring的代理

作者: 凌风x | 来源:发表于2020-03-06 15:30 被阅读0次

    1.静态代理

    静态代理,顾名思义,手动代码代理。通过代理类实现被代理类的接口,进而完成代理过程。其实就是才能重写了,原本的接口方法,手动去在目标方法执行前中后,进行切割,进而实现代理。

    public class TestStaticProxy {
    
        public static void main(String[] args) {
            IRegisterService iRegisterService = new RegisterServiceImpl();
            IRegisterService proxy = new RegisterServiceProxy(iRegisterService);
            proxy.register("RyanLee", "123");
        }
    }
    interface IRegisterService {
        void register(String name, String pwd);
    }
    
    class RegisterServiceImpl implements IRegisterService {
        @Override
        public void register(String name, String pwd) {
            System.out.println(String.format("【向数据库中插入数据】name:%s,pwd:%s", name, pwd));
        }
    }
    
    class RegisterServiceProxy implements IRegisterService {
        IRegisterService iRegisterService;
    
        public RegisterServiceProxy(IRegisterService iRegisterService) {
            this.iRegisterService = iRegisterService;
        }
    
        @Override
        public void register(String name, String pwd) {
            System.out.println("[Proxy]一些前置处理");
            System.out.println(“开始执行被代理的方法”);
            iRegisterService.register(name, pwd);
            System.out.println("[Proxy]一些后置处理");
    
        }
    }
    

    2.JDK代理

    JDK代理,动态代理类和被代理类必须继承同一个接口。动态代理只能对接口中声明的方法进行代理,有一定限制。每一个动态代理实例都有一个关联的InvocationHandler。通过代理实例调用方法,方法调用请求会被转发给InvocationHandler的invoke方法。(这里就可以看出为啥在实例化代理类时,要传入目标类的接口,这样在代理类实现的invoke方法里可以直接执行接口方法实现了目标类被代理的过程)。实际上我们发现JDK的动态代理是基于反射的,而实现方式和静态代理很像,那为啥又说是动态代理呢?其实,细心的小伙伴就已经发现,JDK动态代理这种方式是一种对目标方法的增强,他不关心你目标方法,而是通过newProxyInstance方法来生成新的 \color{#2196F3}{实现接口}的代理对象,只管代理执行,此处解耦。而对比静态代理就需要静态代理类知道目标类的信息,实现目标类的接口,限制很多。而动态代理在实现代理的时候,是传递需要代理类,的实现,无关接口 所以并不需要为每一种接口都写一个代理类了。

     public static void main(String[] args) {
            Target tar = new Target();
            ProxyHandler handler = new ProxyHandler();
            BBQ proxy = (BBQ) handler.getProxy(tar);
            proxy.sayBBQ("LF");
        }
    
        static class Target implements BBQ {
            @Override
            public void sayBBQ(String s) {
                System.out.println("这是原方法执行的 say bbq " + s);
            }
        }
    
        interface BBQ {
            void sayBBQ(String s);
        }
    
        static class ProxyHandler implements InvocationHandler {
            Object obj;
    
            public Object getProxy(Object obj) {
                this.obj = obj;
                Object o = Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
                return o;
            }
    
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                doBefore();
                Object result = method.invoke(obj, args);
                doAfter();
                return result;
            }
    
            private void doBefore() {
                Thread thread = Thread.currentThread();
                System.out.println("[Proxy]一些前置处理" + thread.getName() + " " + thread.getId());
            }
    
            private void doAfter() {
                System.out.println("[Proxy]一些后置处理");
            }
        }
    

    3.cglib代理

    JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。

    public static void main(String[] args) {
            Target tar = new Target();
            CGLIBProxyDemo handler = new CGLIBProxyDemo();
            Target proxy = (Target) handler.getProxy(tar);
            proxy.sayBBQ("cglib代理");
        }
    
        static class Target implements JDKProxyUtil.BBQ {
            @Override
            public void sayBBQ(String s) {
                System.out.println("这是原方法执行的 say bbq " + s);
            }
        }
    
        interface BBQ {
            void sayBBQ(String s);
        }
    
        static class CGLIBProxyDemo implements MethodInterceptor {
            private Object target;
    
            public Object getProxy(Object obj) {
                this.target = obj;
                Enhancer enhancer = new Enhancer();
                //生成子类
                enhancer.setSuperclass(this.target.getClass());
                // 回调方法
                enhancer.setCallback(this);
                // 创建代理对象
                return enhancer.create();
            }
    
            @Override
            public Object intercept(Object obj, Method method, Object[] param, MethodProxy methodProxy) throws Throwable {
                doBefore();
                Object result = methodProxy.invokeSuper(obj, param);
                doAfter();
                return result;
            }
    
            private void doBefore() {
                Thread thread = Thread.currentThread();
                System.out.println("[Proxy]一些前置处理" + thread.getName() + " " + thread.getId());
            }
    
            private void doAfter() {
                System.out.println("[Proxy]一些后置处理");
            }
    
    
        }
    

    结语

    仔细观察会发现:\color{#2196F3}{代理}的原理依据,就是多态,要么实现接口生成代理类,要么继承目标类生成代理类,而\color{#2196F3}{动态}的手段就是反射,利用反射来获取被代理类的信息,进而才能实现不需要了解目标信息来构建多态,从而动态解耦。

    相关文章

      网友评论

          本文标题:Java与Spring的代理

          本文链接:https://www.haomeiwen.com/subject/jfkirhtx.html