使用动态代理的好处是,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; } }