使用Cglib動態代理實現事務管理器

使用動態代理的好處是,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

clipboard.png

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