java 動態代理—— Mybaties 攔截器鏈基本原理實現

1.摘要

  Mybaties 中有個分頁插件,以前有特地的去了解了一下原理 :https://www.cnblogs.com/jonrain0625/p/11168247.html,從瞭解中得知分頁插件是基於Mybaties的攔截器去實現的,這個插件就是一個攔截器,和別的攔截器組成了Mybaties的攔截器鏈,而後全部的攔截器都對Executor 這個類 作了動態代理。本次主要的再次去學習下這個動態代理,去實現一個最基本的攔截器鏈的效果。固然還有spring aop 等不少地方都是基於動態代理去實現的,關於Aop能夠在 :http://www.javashuo.com/article/p-morvsgps-co.html 去了解。本次也是基於這篇文章,及代碼去學習和實現 攔截器鏈。html

2.java動態代理

  java中代理模式分靜態代理和動態代理,而動態代理的實現有兩種實現方法,一種是基於JDK 用 接口方法去實現 ,一種是基於CGLIB 基於類去實現 ,瞭解能夠看:https://www.cnblogs.com/rinack/p/7742682.html 。java

  2.1 JDK 代理的基本使用:

    1.建立代理類的接口spring

    2.實現代理類執行的接口 InvocationHandler設計模式

    3.生成代理對象:Proxy.newProxyInstance(loader, interfaces, h);ide

    4.使用代理對象學習

    

 

 

3.示列  

  示列實現對user類的log方法攔截 ,在執行log方法以前,攔截器鏈中 LogIntercept1 和LogIntercept2 對log 方法攔截 ,作業務邏輯,攔截器鏈優勢的很好體現是,實現耦合,能夠高度的作到對內修改 。測試

  3.1  新建代理類接口 和代理類

  

public interface Log { public void log(); }

 

public class User  implements Log{ String name = "user1"; public void log() { System.out.println("user1 ----- 登錄"); } }

  3.2  新建 InvocationHandler 的實現類

    爲了封裝 , 在bin方法中調用 Proxy.newProxyInstance 建立代理對象 ,把代理對象  和攔截器注入到代理對象,在 invoke方法中用攔截器代理執行。this

  

public class Handler implements InvocationHandler{ //調用對象
    private Object proxy; //目標對象
    private Intercept intercept; private Handler(Intercept target,Object proxy) { this.intercept=target; this.proxy=proxy; } public static Object bind(Intercept target,Object proxy){ return Proxy.newProxyInstance( proxy.getClass().getClassLoader() , proxy.getClass().getInterfaces(), new Handler(target,proxy)); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return intercept.intercept(this.proxy,method,args); } }

  3.3 建立攔截器 

    攔截器和攔截器的實現,偷懶寫在一個文件中spa

  

import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public interface Intercept { Object intercept(Object o, Method m, Object[] os ); } class LogIntercept1 implements Intercept { @Override public Object intercept(Object o, Method m, Object[] os) { try { System.out.println("LogIntercept1 攔截登錄操做 作相關業務邏輯"); return m.invoke(o,os); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { e.printStackTrace(); return null; } } } class LogIntercept2 implements Intercept { @Override public Object intercept(Object o, Method m, Object[] os) { try { System.out.println("LogIntercept2 攔截登錄操做,作相關業務邏輯"); return m.invoke(o,os); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { e.printStackTrace(); return null; } } }

 

 3.4 建立一個代理工廠 

    在類中根據攔截器的數量,對代理類作循環。每次代理都把攔截器傳入代理對象中 。插件

  

package 設計模式.com.pox.logPoxy; import java.util.ArrayList; import java.util.List; public class ProxyFactory { List<Intercept> InterceptChain = new ArrayList<Intercept>() { private static final long serialVersionUID = 1L; { add(new LogIntercept1()); add(new LogIntercept2()); } }; public  Object  proxy(Class<?> classz) throws Exception { try { Object obj = classz.newInstance(); return InterceptAll(obj); } catch (InstantiationException | IllegalAccessException e) { throw new RuntimeException("代理異常");//拋出個異常,不另外設計異常類了,用RuntimeException 代替
 } } /** 攔截器代理 * @param obj * @return
     */
    private Object InterceptAll(Object obj) { if(InterceptChain.isEmpty()) { return obj; } for (Intercept intercept : InterceptChain) { obj = Handler.bind(intercept,obj); } return obj; } // 一下是單列的建立模式
    public ProxyFactory(){ if(inner.proxyFactory != null) { throw new RuntimeException("不容許建立多個實例"); } } public static ProxyFactory getProxyFactory() { return inner.proxyFactory; } private static class inner{ static ProxyFactory proxyFactory = new ProxyFactory(); } }

 

 

  3.5 測試

public class Test { public static void main(String[] args) throws Exception { ProxyFactory proxyFactory = ProxyFactory.getProxyFactory(); Log user = (Log) proxyFactory.proxy(User.class); user.log(); } } /** ouput : LogIntercept2 攔截登錄操做 LogIntercept1 攔截登錄操做 user1 ----- 登錄 */

 

 

以上就是一個簡單的攔截器鏈實現,能夠去查閱Mybaties的攔截器鏈,其原理是同樣的,若是業務須要增長個攔截器鏈,實現接口 Intercept ,添加到代理工廠 ProxyFactory 攔截器鏈 InterceptChain中便可,實現高度的解耦功能。

相關文章
相關標籤/搜索