1

使用动态代理的好处是,Java反射机制可以生成任意类型的动态代理类。
如果使用proxy的动态代理的话,每个类都需要一个接口。Cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强。

以下是我使用Cglib来实现事务管理器的实例。
1、RouteDispatcherServlet.java
这个servlet主要是用于处理路由跳转的问题,所有的Action跳转都需要经过这个servlet。路径解析得到的类名和方法名,在此调用所有的Action方法。
同时事务也在这里实现。事务的实现由Cglib实现。

web.xml:

<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);
    }
    
}

2、TransactionCglib.java
在TransactionCglib中实现了MethodInterceptor的接口。在这里需要导入两个jar包:

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;
    }

}

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;
    }
}

sll
23 声望2 粉丝