JAVA学习日志3-5(spring 动态代理)

tech2022-08-07  140

动态代理 代理可以理解为在某个操作前后添加另一些操作,如在进行转账操作前添加开启手动提交事务的操作,在转账操作结束后添加提交事务或回滚事务的操作。如果转账操作记为A操作,添加了事务后的A操作就可以成为A操作的代理。当使用A操作时使用的A操作的代理。事务的操作并不是业务操作,和转账业务是不想关,所以需要将二者进行分离。 需要在transfer内的代码中添加事务相关的代码

静态代理 由于dao层使用connection对象是从链接池中会获取的,每个操作可能不再同一个链接上,所以直接进行事务操作时不合理的。可以定义一个容器来存储connection,时dao和service都使用同一对象。在一个线程中线程对象是不会变的,所有可以使用map来存储范型是<Thread,Connection>。在定义一个connection管理类来负责线程的操作(分发连接,开启事务等) public class ConnStore { private static Map<Thread, Connection> connMap = new HashMap<Thread, Connection>(); public static void putConn(Connection conn){ connMap.put(Thread.currentThread(),conn); } public static Connection getConn(Thread thread){ return connMap.get(thread); } public static void remove(Thread thread){ connMap.remove(thread); } } public class ConnManage { public static Connection getConn(){ Connection conn = null; try { if(ConnStore.getConn(Thread.currentThread())==null){ DataSource ds = new ComboPooledDataSource("c3p0-config.xml"); conn = ds.getConnection(); ConnStore.putConn(conn); } } catch (SQLException e) { e.printStackTrace(); } return ConnStore.getConn(Thread.currentThread()); } public static void setAutoCommit(){ Connection conn = getConn(); try { conn.setAutoCommit(false); } catch (SQLException e) { e.printStackTrace(); } } public static void commit(){ Connection conn = ConnStore.getConn(Thread.currentThread()); try { conn.commit(); } catch (SQLException e) { e.printStackTrace(); } } public static void callback(){ Connection conn = ConnStore.getConn(Thread.currentThread()); try { conn.rollback(); } catch (SQLException e) { e.printStackTrace(); } } } public class UserDaoImpl implements UserDao { QueryRunner queryRunner = new QueryRunner(); public User findUser(String uname) { String sqlStr = "select * from user where uname = ?"; User user = null; try { user = queryRunner.query(ConnManage.getConn(),sqlStr,new BeanHandler<User>(User.class),uname); } catch (SQLException e) { e.printStackTrace(); } return user; } public int updae(User user) { String sqlStr = "update user set money = ? where uname = ?"; Object []objects = {user.getMoney(),user.getUname()}; int num = -1; try { num = queryRunner.update(ConnManage.getConn(),sqlStr,objects); } catch (SQLException e) { e.printStackTrace(); } return num; } } public class UserServiceImpl implements UserService { private UserDao userDao = new UserDaoImpl(); public void transfer(String name1, String name2, int monney) { try { //找到对象,进行转账 User user1 = userDao.findUser(name1); User user2 = userDao.findUser(name2); user1.setMoney(user1.getMoney()-monney); user2.setMoney(user2.getMoney()+monney); ConnManage.setAutoCommit(); userDao.updae(user1); // int num = 0/0; userDao.updae(user2); ConnManage.commit(); } catch (Exception e) { ConnManage.callback(); } } } 动态代理(Proxy) 在上述操作中dao层的业务代码和事务代码没有进行分离 使用动态代理来进行分离,程序在运行期间才产生添加了操作类 代理对象中需要获得被代理的对象,这里通过构造方法传递 public class UserProxy implements InvocationHandler { private UserService userService; public UserProxy(UserService userService){ this.userService=userService; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { //添加事务操作 ConnManage.setAutoCommit(); //通过反射进行业务操作 method.invoke(userService,args); //提交事务 ConnManage.commit(); } catch (Exception e) { //回滚事务 ConnManage.callback(); } return null; } }

service层

public class UserServiceImpl2 implements UserService { public UserDao userDao = new UserDaoImpl(); public void transfer(String name1, String name2, int monney) { User user1 = userDao.findUser(name1); User user2 = userDao.findUser(name2); user1.setMoney(user1.getMoney()-monney); user2.setMoney(user2.getMoney()+monney); userDao.updae(user1); userDao.updae(user2); } }

调用,userService2是userService 的代理对象,添加了事务的操作

@org.junit.Test public void Test2(){ UserService userService = new UserServiceImpl2(); UserService userService2 = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(), userService.getClass().getInterfaces(),new UserProxy(userService)); userService2.transfer("a","b",10); } 动态代理(cglib) public class UserCglib implements InvocationHandler { private UserService userService; public UserCglib(UserService userService){ this.userService=userService; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { ConnManage.setAutoCommit(); method.invoke(userService,args); ConnManage.commit(); } catch (Exception e) { ConnManage.callback(); } return null; } }

调用

@org.junit.Test public void Test3(){ UserService userService = new UserServiceImpl2(); Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(UserService.class); enhancer.setCallback(new UserCglib(userService)); UserService userService1 = (UserService) enhancer.create(); userService1.transfer("a","b",5); }
最新回复(0)