使用動態代理的好處是,Java反射機制能夠生成任意類型的動態代理類。
若是使用proxy的動態代理的話,每一個類都須要一個接口。Cglib是針對類來實現代理的,他的原理是對指定的目標類生成一個子類,並覆蓋其中方法實現加強。java
如下是我使用Cglib來實現事務管理器的實例。
一、RouteDispatcherServlet.java
這個servlet主要是用於處理路由跳轉的問題,全部的Action跳轉都須要通過這個servlet。路徑解析獲得的類名和方法名,在此調用全部的Action方法。
同時事務也在這裏實現。事務的實現由Cglib實現。mysql
web.xml:web
<servlet> <servlet-name>RouteDispatcherServlet</servlet-name> <servlet-class>kit.RouteDispatcherServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>RouteDispatcherServlet</servlet-name> <url-pattern>/action/*</url-pattern> </servlet-mapping>
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); } }
二、TransactionCglib.java
在TransactionCglib中實現了MethodInterceptor的接口。在這裏須要導入兩個jar包:sql
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; } }
三、Transaction.java數據庫
public interface Transaction { public void transaction() throws Exception; }
四、TransactionManager.java
TransactionManager體現了事務提交和rollback的流程,當無異常時commit,當有異常的時候,事務回滾rollback。app
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 } } }
五、TransactionDao.java
TransactionDao中放置的是關於事務的詳細操做,包括getTransaction、commmit、rollback。須要注意的是,在這裏,變量和方法都是靜態的,這就保證了在使用的時候僅僅只有一個connection,保證了事務的正確性。ide
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; } }