• 设计模式(代理模式)


    一、简介

    代理模式是设计模式中很常见的一种设计模式,使用代理对象完成用户的请求,屏蔽用户对真是对象的访
    问。使用代理模式的意图很多,比如因安全原因需要屏蔽客户端直接访问真是对象;或者在远程调用中需
    要使用代理对象处理远程方法调用的技术细节(如RMI);也可以是为了提升系统系能对真是对象进行封
    装,从而达到延迟加载的目的。

    二、使用场景及优点

    1.因安全原因考虑屏蔽真实对象,提高对敏感数据的保护,提升程序的安全界别。
    2.封装实现细节,封装程序的实现细节,保护敏感的业务规则。
    3.实现延迟加载,提升系统的启动、运行熟读,提高用户体验。

    三、实现原理

    1.接口类

    public interface IWetherService
    {
        String getWether(String areaNo);
    }

    2.实现类

    public class WetherService implements IWetherService
    {
        Map<String,String> wetherInfoMap = new HashMap<String,String>();
        
        public WetherService(){
            System.out.println("********WetherService Initial*********");
            try
            {
                Thread.sleep(1000);
                wetherInfoMap.put("001", "北京:13C 晴  PM2.5 140");
                wetherInfoMap.put("002", "上海:19C 晴  PM2.5 100");
                wetherInfoMap.put("003", "深圳:31C 晴  PM2.5 60");
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
        
        @Override
        public String getWether(String areaNo)
        {
            System.out.println("********WetherService getWether*********");
            return wetherInfoMap.get(areaNo);
        }
        
    }

    3.代理类,代理类比原始的类初始化速度快,实现了延迟加载,提升了系统启动速度,提高了用户体验

    public class WetherServiceProxy implements IWetherService
    {
        WetherService ws = null;
        
        @Override
        public String getWether(String areaNo)
        {
            String wether = null;
            System.out.println("*******WetherServiceProxy:before getWether*******");
            if(ws == null){
                ws = new WetherService();
            }
            wether = ws.getWether(areaNo);
            System.out.println("*******WetherServiceProxy:after getWether*******");
            return wether;
        }
    }

    4.测试代码,在使用服务时不再使用真实的服务实例而是使用它的代理类简介使用相关服务。

    @Test
    public void getWetherInfo(){
        IWetherService ws = new WetherServiceProxy();
        String wether = ws.getWether("001");
        Assert.assertEquals("北京:13C 晴  PM2.5 140", wether);
        
        wether = ws.getWether("002");
        Assert.assertEquals("上海:19C 晴  PM2.5 100", wether);
        
        wether = ws.getWether("003");
        Assert.assertEquals("深圳:31C 晴  PM2.5 60", wether);
    }

    四、动态代理

    1.动态代理是指在运行时,通过字节码动态生成加载技术生成代理类。与静态代理相比有诸多好处:
    (1).不需要为真实主题写一个形式上完全一样的封装类,提高开发效率,减少维护难度。
    (2).使用动态代理的生成方法可以在运行时指定代理类的执行逻辑,大大提升系统的灵活性。
    2.动态代理的实现方式(JDK、 CGLIB、 Javassist):
    (1).JDK动态代理

    public class JDKDynamicProxyHeadler implements InvocationHandler{
    
        IWetherService ws = null;
        /**
         * 绑定委托对象并返回一个代理类
         */
        public IWetherService createJDKProxy(){
            return (IWetherService)Proxy.newProxyInstance(this.getClass().getClassLoader(),
                    new Class[]{IWetherService.class},
                    this);
        }
        
        @Override
        public Object invoke(Object proxy, Method method, Object [] args) throws Throwable
        {
            if(ws == null)
                ws = new WetherService();
            return method.invoke(ws, args);
        }
    }

    测试代码:

    public class JDKDynamicProxyTest{
        @Test
        public void getWetherInfo(){
    //        IWetherService jdkProxy = new JDKDynamicProxyHeadler().createJDKProxy();
            IWetherService jdkProxy = getJDKProxy(WetherService.class, new JDKDynamicProxyHeadler());
            String wether = jdkProxy.getWether("001");
            Assert.assertEquals("北京:13C 晴  PM2.5 140", wether);
            
            wether = jdkProxy.getWether("002");
            Assert.assertEquals("上海:19C 晴  PM2.5 100", wether);
            
            wether = jdkProxy.getWether("003");
            Assert.assertEquals("深圳:31C 晴  PM2.5 60", wether);
        }
        
        @SuppressWarnings("unchecked")
        public <T> T getJDKProxy(Class<?> clazz, InvocationHandler handler){
            return (T)Proxy.newProxyInstance(clazz.getClassLoader(),
                    clazz.getInterfaces(),
                    handler);
        }
    }

    (2).CGLIB动态代理

    public class CglibDynamicProxyInterceptor implements MethodInterceptor{
    
        IWetherService ws = null;
        
        @Override
        public Object intercept(Object proxy, Method method, Object[] arg2, MethodProxy proxyMethod) 
            throws Throwable
        {
            if(ws == null)
                ws = new WetherService();
            return method.invoke(ws, arg2);
        }
    }

    测试代码:

    public class CglibDynamicProxyTest{
        @Test
        public void getWetherInfo(){
            IWetherService jdkProxy = getCglibProxy(WetherService.class, new CglibDynamicProxyInterceptor());
            String wether = jdkProxy.getWether("001");
            Assert.assertEquals("北京:13C 晴  PM2.5 140", wether);
            
            wether = jdkProxy.getWether("002");
            Assert.assertEquals("上海:19C 晴  PM2.5 100", wether);
            
            wether = jdkProxy.getWether("003");
            Assert.assertEquals("深圳:31C 晴  PM2.5 60", wether);
        }
        
        @SuppressWarnings("unchecked")
        public <T> T getCglibProxy(Class<?> clazz, MethodInterceptor interceptor){
            Enhancer enhancer = new Enhancer();
            enhancer.setCallback(interceptor);
            enhancer.setInterfaces(clazz.getInterfaces());
            return (T)enhancer.create();
        }
    }

    (3).Javassist动态代理

    public class JavassistDynamicProxyHandler implements MethodHandler{
        
        IWetherService ws = null;
        
        @Override
        public Object invoke(Object arg0, Method method, Method arg2, Object [] arg3) 
            throws Throwable
        {
            if(ws == null)
                ws = new WetherService();
            return method.invoke(ws, arg3);
        }
    }

    测试代码:

    public class JavassistDynamicProxyTest{
        
        @Test
        public void getWetherInfo(){
            IWetherService jdkProxy = getJavassistProxy2(WetherService.class, new JavassistDynamicProxyHandler(), IWetherService.class);
            String wether = jdkProxy.getWether("001");
            Assert.assertEquals("北京:13C 晴  PM2.5 140", wether);
            
            wether = jdkProxy.getWether("002");
            Assert.assertEquals("上海:19C 晴  PM2.5 100", wether);
            
            wether = jdkProxy.getWether("003");
            Assert.assertEquals("深圳:31C 晴  PM2.5 60", wether);
        }
        
        /*
         * 通过代理工厂
         */
        @SuppressWarnings("unchecked")
        public <T> T getJavassistProxy(Class<?> clazz, MethodHandler methodHandler){
            T jproxy = null;
            ProxyFactory proxyFactory = new ProxyFactory();
            proxyFactory.setInterfaces(clazz.getInterfaces());
            Class<?> proxyClass = proxyFactory.createClass();
            try
            {
               jproxy = (T)proxyClass.newInstance();
               ((ProxyObject)jproxy).setHandler(methodHandler);
            }
            catch(InstantiationException e)
            {
                e.printStackTrace();
            }
            catch(IllegalAccessException e)
            {
                e.printStackTrace();
            }
            return jproxy;
        }
        
        /*
         * 通过代理工厂
         */
        @SuppressWarnings("unchecked")
        public <T> T getJavassistProxy1(Class<?> clazz, MethodHandler methodHandler){
            T jproxy = null;
            ProxyFactory proxyFactory = new ProxyFactory();
            proxyFactory.setInterfaces(clazz.getInterfaces());
            try
            {
                jproxy = (T)proxyFactory.create(null, null, methodHandler);
            }
            catch(IllegalArgumentException e)
            {
                e.printStackTrace();
            }
            catch(NoSuchMethodException e)
            {
                e.printStackTrace();
            }
            catch(InstantiationException e)
            {
                e.printStackTrace();
            }
            catch(IllegalAccessException e)
            {
                e.printStackTrace();
            }
            catch(InvocationTargetException e)
            {
                e.printStackTrace();
            }
            return jproxy;
        }
        
        /*
         * Java动态代码创建代理
         */
        public <T> T getJavassistProxy2(Class<?> clazz, MethodHandler methodHandler, Class<T> clat) {
            T jproxy = null;
            try
            {
                ClassPool mPool = new ClassPool(true);
                //定义接口名字
                CtClass mCtc = mPool.makeClass(clat.getName()+"-javassist-proxy");
                //需要实现的接口
                mCtc.addInterface(mPool.get(clat.getName()));
                //添加构造函数
                mCtc.addConstructor(CtNewConstructor.defaultConstructor(mCtc));
                //添加字段的地段信息,使用动态java代码
                mCtc.addField(CtField.make("public "+clat.getName() + " ws;", mCtc));
                
                //添加方法,使用动态Java代码指定内部逻辑
                String name = WetherService.class.getName();
                StringBuilder businessCode = new StringBuilder();
                businessCode.append("public String getWether(String areNo) {");
                businessCode.append("  if(ws == null) ws = new "+name+"(); ");
                businessCode.append(" return ws.getWether(areNo); }");
                
                mCtc.addMethod(CtNewMethod.make(businessCode.toString(), mCtc));
                //基于以上逻辑生成动态类
                @SuppressWarnings("unchecked")
                Class<T> pc = (Class<T>)mCtc.toClass();
                //生成动态类的实例
                jproxy = pc.newInstance();
            }
            catch(Exception e)
            {
                e.printStackTrace();
            }
            return jproxy;
        }
    }






  • 相关阅读:
    GAMIT中遇到的错误
    bash: ./install_software: Permission denied
    xmanager无法加载远程桌面
    GMT的安装
    小总结:Gamit中常见常用命令
    动态分配指针数组(以解决)
    Gamit使用gftp软件下载数据
    Python基础(1)
    JAVA中关于多线程的理解
    JAVA 基本绘图——利用JFrame JPanel 绘制扇形
  • 原文地址:https://www.cnblogs.com/pocter/p/3684456.html
Copyright © 2020-2023  润新知