摘要:使用动态代理的好处是,反射机制可以生成任意类型的动态代理类。暂时不做处理得到类名得到方法名创建实例动态代理实现事务得到方法调用的方法在中实现了的接口。恢复事务的默认提交方式关闭数据库连接
使用动态代理的好处是,Java反射机制可以生成任意类型的动态代理类。
如果使用proxy的动态代理的话,每个类都需要一个接口。Cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强。
以下是我使用Cglib来实现事务管理器的实例。
1、RouteDispatcherServlet.java
这个servlet主要是用于处理路由跳转的问题,所有的Action跳转都需要经过这个servlet。路径解析得到的类名和方法名,在此调用所有的Action方法。
同时事务也在这里实现。事务的实现由Cglib实现。
web.xml:
RouteDispatcherServlet kit.RouteDispatcherServlet RouteDispatcherServlet /action/*
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; } }
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/65963.html
摘要:由于的限制,无法替换被代理类已经被载入的字节码,只能生成并载入一个新的子类作为代理类,被代理类的字节码依然存在于中。区别于前两者,是一种静态代理的实现,即在编译时或者载入类时直接修改被代理类文件的字节码,而非运行时实时生成代理。 现象描述 上周同事发现其基于mySql实现的分布式锁的线上代码存在问题,代码简化如下: @Controller class XService { @A...
摘要:动态代理又被称为代理或接口代理。静态代理在编译时产生字节码文件,可以直接使用,效率高。代理无需实现接口,通过生成类字节码实现代理,比反射稍快,不存在性能问题,但会继承目标对象,需要重写方法,所以目标对象不能为类。 一、代理模式介绍 代理模式是一种设计模式,提供了对目标对象额外的访问方式,即通过代理对象访问目标对象,这样可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功...
摘要:值得一提的是由于采用动态创建子类的方式生成代理对象,所以不能对目标类中的方法进行代理。动态代理中生成的代理类是子类,调试的时候可以看到,打开源码可看到实现了和也就实现方法。 前面讲到了动态代理的底层原理,接下来我们来看一下aop的动态代理.Spring AOP使用了两种代理机制:一种是基于JDK的动态代理,一种是基于CGLib的动态代理. ①JDK动态代理:使用JDK创建代理有一个限制...
Java的三种代理模式 参考:http://www.cnblogs.com/cenyu/...Java核心技术原书第九版6.5节 为什么使用代理 我们在写一个功能函数时,经常需要在其中写入与功能不是直接相关但很有必要的代 码,如日志记录,信息发送,安全和事务支持等,这些枝节性代码虽然是必要的,但它会带来以下麻烦: 枝节性代码游离在功能性代码之外,它不是函数的目的,这是对OO是一种破坏 枝节性...
阅读 2457·2019-08-30 15:53
阅读 2572·2019-08-29 13:11
阅读 2653·2019-08-29 12:45
阅读 3486·2019-08-29 12:41
阅读 2326·2019-08-26 10:14
阅读 2154·2019-08-23 14:39
阅读 2314·2019-08-23 12:38
阅读 3378·2019-08-23 12:04