动态代理
代理可以理解为在某个操作前后添加另一些操作,如在进行转账操作前添加开启手动提交事务的操作,在转账操作结束后添加提交事务或回滚事务的操作。如果转账操作记为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);
}