使用动态代理的好处是,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包:
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://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。