摘要:使用動態代理的好處是,反射機制可以生成任意類型的動態代理類。暫時不做處理得到類名得到方法名創建實例動態代理實現事務得到方法調用的方法在中實現了的接口。恢復事務的默認提交方式關閉數據庫連接
使用動態代理的好處是,Java反射機制可以生成任意類型的動態代理類。
如果使用proxy的動態代理的話,每個類都需要一個接口。Cglib是針對類來實現代理的,他的原理是對指定的目標類生成一個子類,并覆蓋其中方法實現增強。
以下是我使用Cglib來實現事務管理器的實例。
1、RouteDispatcherServlet.java
這個servlet主要是用于處理路由跳轉的問題,所有的Action跳轉都需要經過這個servlet。路徑解析得到的類名和方法名,在此調用所有的Action方法。
同時事務也在這里實現。事務的實現由Cglib實現。
web.xml:
RouteDispatcherServlet kit.RouteDispatcherServlet RouteDispatcherServlet /action/*
public class RouteDispatcherServlet extends HttpServlet { private static final long serialVersionUID = 3483132493821191287L; @Override public void init() throws ServletException { //暫時不做處理 } @Override public void doGet(HttpServletRequest request,HttpServletResponse response){ StringBuffer url = request.getRequestURL(); //得到類名 String actionNameTemp = url.substring(0,url.lastIndexOf("/")); String actionName = actionNameTemp.substring(actionNameTemp.lastIndexOf("/")+1); String actionWholeName = "action." + actionName; //得到方法名 String methodName = url.substring(url.lastIndexOf("/")+1); try { //創建action實例 BaseAction action = (BaseAction)Class.forName(actionWholeName).newInstance(); //動態代理實現事務 TransactionCglib transactionCglib = new TransactionCglib(); BaseAction baseActionCglib = (BaseAction) transactionCglib.getInstance(action); //得到方法 Method m1 = baseActionCglib.getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class ); //調用baseActionCglib的m1方法 m1.invoke(baseActionCglib, request, response); } catch (Exception e) { e.printStackTrace(); } } @Override public void doPost(HttpServletRequest request,HttpServletResponse response){ this.doGet(request, response); } }
2、TransactionCglib.java
在TransactionCglib中實現了MethodInterceptor的接口。在這里需要導入兩個jar包:
public class TransactionCglib implements MethodInterceptor{ private Object target; public TransactionCglib(){ TransactionDao.getTransaction();//得到連接,開始事務 } /** * 創建代理對象 * * @param target * @return */ public Object getInstance(Object target){ this.target = target; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.target.getClass()); enhancer.setCallback(this); return enhancer.create(); } /* (non-Javadoc) * * 使用cglib實現事務 * */ public Object intercept(final Object obj, Method method, final Object[] args, final MethodProxy proxy) throws Throwable { //事務開始 TransactionManager transactionManager = new TransactionManager(TransactionDao.getConn()); transactionManager.doTransaction(new Transaction(){ public void transaction() throws Exception { try { proxy.invokeSuper(obj, args); } catch (Throwable e) { throw new Exception(e); } } }); return null; } }
3、Transaction.java
public interface Transaction { public void transaction() throws Exception; }
4、TransactionManager.java
TransactionManager體現了事務提交和rollback的流程,當無異常時commit,當有異常的時候,事務回滾rollback。
public class TransactionManager { private Connection conn; public TransactionManager(Connection conn){ this.conn = conn; } public void doTransaction(Transaction transaction) throws Exception{ try { transaction.transaction(); TransactionDao.commit(); } catch (Exception e) { TransactionDao.rollback(); }finally{ //close } } }
5、TransactionDao.java
TransactionDao中放置的是關于事務的詳細操作,包括getTransaction、commmit、rollback。需要注意的是,在這里,變量和方法都是靜態的,這就保證了在使用的時候僅僅只有一個connection,保證了事務的正確性。
public class TransactionDao { private static Connection conn; public static Connection getTransaction(){ try { Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/tradition","root","sll"); conn.setAutoCommit(false); } catch (Exception e) { e.printStackTrace(); } return conn; } public static void commit(){ try { conn.commit(); conn.setAutoCommit(true);//恢復jdbc事務的默認提交方式 conn.close(); } catch (SQLException e) { e.printStackTrace(); } } public static void rollback(){ try { conn.rollback(); conn.close();//關閉數據庫連接 } catch (SQLException e) { e.printStackTrace(); } } public static Connection getConn() { return conn; } public static void setConn(Connection conn) { TransactionDao.conn = conn; } }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/65963.html
摘要:由于的限制,無法替換被代理類已經被載入的字節碼,只能生成并載入一個新的子類作為代理類,被代理類的字節碼依然存在于中。區別于前兩者,是一種靜態代理的實現,即在編譯時或者載入類時直接修改被代理類文件的字節碼,而非運行時實時生成代理。 現象描述 上周同事發現其基于mySql實現的分布式鎖的線上代碼存在問題,代碼簡化如下: @Controller class XService { @A...
摘要:動態代理又被稱為代理或接口代理。靜態代理在編譯時產生字節碼文件,可以直接使用,效率高。代理無需實現接口,通過生成類字節碼實現代理,比反射稍快,不存在性能問題,但會繼承目標對象,需要重寫方法,所以目標對象不能為類。 一、代理模式介紹 代理模式是一種設計模式,提供了對目標對象額外的訪問方式,即通過代理對象訪問目標對象,這樣可以在不修改原目標對象的前提下,提供額外的功能操作,擴展目標對象的功...
摘要:值得一提的是由于采用動態創建子類的方式生成代理對象,所以不能對目標類中的方法進行代理。動態代理中生成的代理類是子類,調試的時候可以看到,打開源碼可看到實現了和也就實現方法。 前面講到了動態代理的底層原理,接下來我們來看一下aop的動態代理.Spring AOP使用了兩種代理機制:一種是基于JDK的動態代理,一種是基于CGLib的動態代理. ①JDK動態代理:使用JDK創建代理有一個限制...
Java的三種代理模式 參考:http://www.cnblogs.com/cenyu/...Java核心技術原書第九版6.5節 為什么使用代理 我們在寫一個功能函數時,經常需要在其中寫入與功能不是直接相關但很有必要的代 碼,如日志記錄,信息發送,安全和事務支持等,這些枝節性代碼雖然是必要的,但它會帶來以下麻煩: 枝節性代碼游離在功能性代碼之外,它不是函數的目的,這是對OO是一種破壞 枝節性...
閱讀 2457·2019-08-30 15:53
閱讀 2572·2019-08-29 13:11
閱讀 2653·2019-08-29 12:45
閱讀 3486·2019-08-29 12:41
閱讀 2326·2019-08-26 10:14
閱讀 2154·2019-08-23 14:39
閱讀 2314·2019-08-23 12:38
閱讀 3378·2019-08-23 12:04