設計模式(代理模式)

1、簡介

代理模式是設計模式中很常見的一種設計模式,使用代理對象完成用戶的請求,屏蔽用戶對真是對象的訪
問。使用代理模式的意圖不少,好比因安全緣由須要屏蔽客戶端直接訪問真是對象;或者在遠程調用中需
要使用代理對象處理遠程方法調用的技術細節(如RMI);也能夠是爲了提高系統系能對真是對象進行封
裝,從而達到延遲加載的目的。java

2、使用場景及優勢

1.因安全緣由考慮屏蔽真實對象,提升對敏感數據的保護,提高程序的安全界別。
2.封裝實現細節,封裝程序的實現細節,保護敏感的業務規則。
3.實現延遲加載,提高系統的啓動、運行熟讀,提升用戶體驗。設計模式

3、實現原理

1.接口類安全

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

2.實現類app

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.代理類,代理類比原始的類初始化速度快,實現了延遲加載,提高了系統啓動速度,提升了用戶體驗ide

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);
}

4、動態代理

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);
    }
}

測試代碼:ui

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動態代理this

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);
    }
}

測試代碼:spa

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;
    }
}
相關文章
相關標籤/搜索