zoukankan      html  css  js  c++  java
  • 常用设计模式--代理模式

    代理模式是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。

    代理又分为静态代理和动态代理,我们一般指的都是动态代理。

    在 Java 中,动态代理有两种:JDK 动态代理cglib 动态代理

    JDK代理

    接口

    public interface HelloWorld {
        void sayHelloWorld();
    }
    

    实现类

    public class HelloWorldImpl implements HelloWorld{
        @Override
        public void sayHelloWorld() {
            System.out.println("Hello world");
        }
    }
    

    代理类

    public class JdkProxyExample implements InvocationHandler {
    
        /*
            这个就是我们要代理的真实对象
         */
        private Object target = null;
    
        //返回代理类的一个实例,返回后的代理类可以当作被代理类使用
        /*
        static Object newProxyInstance(ClassLoaderloader, Class[] interfaces, InvocationHandler h)
        第一参数:类加载器
        第二参数:创建袋里实例需要的一组接口
        第三参数:整合了业务逻辑和横切逻辑的编织器对象
         */
        public Object bind(Object target){
            this.target = target;
            return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                    target.getClass().getInterfaces(),this);
        }
    
    
        /*
            第一个参数proxy一般是指代理类,
            method是被代理的方法,如上例中的request(),
            args为该方法的参数数组。
            这个抽象方法在代理类中动态实现。
         */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("进入代理逻辑方法");
            System.out.println("在调度真实对象之前的服务");
            Object obj = method.invoke(target, args);
            System.out.println("在调度真实对象之后的服务");
            return obj;
        }
    }
    

    测试类

    public class TestMain {
        public static void main(String[] args) {
            JdkProxyExample jdk = new JdkProxyExample();
            //将代理的实例传入,返回真实的代理对象
            HelloWorld proxy = (HelloWorld) jdk.bind(new HelloWorldImpl());
            //真实代理对象调用方法
            proxy.sayHelloWorld();
        }
    }
    

    结果

    可以看出,jdk 代理的重点在于 Proxy.newProxyInstance() 方法和 invoke() 方法。

    代理类继承了Proxy类并且实现了要代理的接口,由于java不支持多继承,所以JDK动态代理不能代理类,只能代理接口。


    cglib代理

    使用 cglib 代理需要单独导入相应的 jar包

    被代理类

    public class SayHello {
        public void sey(String name){
            System.out.println("Hello "+ name);
        }
    }
    

    代理类

    public class CglbProxyExample implements MethodInterceptor {
    
        public Object getProxy(Class cls){
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(cls);
            enhancer.setCallback(this);
            return enhancer.create();
        }
    
        @Override
        public Object intercept(Object obj, Method method,
                                Object[] objects, MethodProxy methodProxy) throws Throwable {
            System.out.println("调用真实对象前");
            Object result = methodProxy.invokeSuper(obj, objects);
            System.out.println("调用真实对后");
            return result;
        }
    }
    

    测试类

    public class TestCglibMain {
        public static void main(String[] args) {
            CglbProxyExample cglib = new CglbProxyExample();
            SayHello proxy = (SayHello) cglib.getProxy(SayHello.class);
            proxy.sey("张三");
        }
    }
    
  • 相关阅读:
    https authorization basic
    第二十一章 单例模式
    第十九章 组合模式
    第十八章 备忘录模式
    第十七章 适配器模式
    第十六章 状态模式
    新博客~
    CF922D Robot Vacuum Cleaner
    BZOJ1767 [CEOI2009]harbingers
    树的直径学习笔记
  • 原文地址:https://www.cnblogs.com/luler/p/14982122.html
Copyright © 2011-2022 走看看