java 使用动态代理 - ThreadLocal实现事务管理

标签: java 代理 threadlocal | 发表时间:2013-05-13 18:30 | 作者:
出处:http://www.iteye.com

 

动态代理:JDK动态代理只能对实现了接口的类进入代理,采用JDK动态代理必须实现InvocationHandler接口,采用Proxy 类创建相应的代理类.
下面使用Model2(MVC)使用代理事务查询用户基本信息,使用DB2数据库:
建立表:
create table T_USER
(
   USER_ID              VARCHAR(10)            not null,
   USER_NAME            VARCHAR(30)            not null,
   PASSWORD             VARCHAR(20)            not null,
   CONTACT_TEL          VARCHAR(30),
   EMAIL                VARCHAR(30),
   CREATE_DATE          DATE,
   constraint P_KEY_1 primary key (USER_ID)
);

初始化数据:
insert into t_user(user_id, user_name, password) values('root', '系统管理员', 'root');
 
ConnectionManager :数据库连接管理类,实现对数据库连接和事务的管理.
package gd.hz.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class ConnectionManager {
	private ConnectionManager() {
	}

	private static ThreadLocal<Connection> threadConn = new ThreadLocal<Connection>();

	// 获取数据库连接
	public static Connection getConnection() {
		Connection conn = threadConn.get();
		if (conn == null) {
			try {
				Class.forName("com.ibm.db2.jcc.DB2Driver");
				conn = DriverManager.getConnection(
						"jdbc:db2://127.0.0.1:50000/DRP", "db2admin", "619100");
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			threadConn.set(conn);
		}
		return conn;
	}

	// 设置事务手动提交
	public static void benigTransction(Connection conn) {
		try {
			if (conn != null) {
				if (conn.getAutoCommit()) {
					conn.setAutoCommit(false);
				}
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	// 提交事务
	public static void endTransction(Connection conn) {
		try {
			if (conn != null) {
				if (!conn.getAutoCommit()) {
					conn.commit();
				}
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	// 设置Connection的原始状态
	public static void recoverTransction(Connection conn) {
		try {
			if (conn != null) {
				if (conn.getAutoCommit()) {
					conn.setAutoCommit(false);
				} else {
					conn.setAutoCommit(true);
				}
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	// 发生异常回滚事务
	public static void rollback(Connection conn) {
		try {
			if (conn != null) {
				conn.rollback();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	// 关闭连接,并将其从当前线程删除
	public static void close() {
		Connection conn = threadConn.get();
		if (conn != null) {
			try {
				conn.close();
				conn = null;
				threadConn.remove();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
}
 

 

Model:
package gd.hz.model;

import java.util.Date;

//用户实体类
public class User {
	// 用户ID
	private String id;
	// 用户名称
	private String name;
	// 登陆密码
	private String password;
	// 联系电话
	private String contact_tel;
	// 电子邮件
	private String email;
	// 用户创建日期
	private Date create_date;

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getContact_tel() {
		return contact_tel == null ? "" : contact_tel;
	}

	public void setContact_tel(String contact_tel) {
		this.contact_tel = contact_tel;
	}

	public String getEmail() {
		return email == null ? "" : email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public Date getCreate_date() {
		return create_date;
	}

	public void setCreate_date(Date create_date) {
		this.create_date = create_date;
	}
}
 
DAO接口:
package gd.hz.dao;

import gd.hz.model.User;

import java.sql.SQLException;

public interface UserDAO {
	public User selUser(String id) throws SQLException;
}
 
DAO实现类:
package gd.hz.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import gd.hz.model.User;
import gd.hz.util.ConnectionManager;

public class UserDAOImpl implements UserDAO {
	// 根据ID查询用户
	public User selUser(String id) throws SQLException {
		ResultSet resu = null;
		String sql = "SELECT * FROM DB2ADMIN.T_USER WHERE USER_ID = ?";
		Connection conn = ConnectionManager.getConnection();
		PreparedStatement pstat = conn.prepareStatement(sql);
		User user = null;
		try {
			pstat.setString(1, id);
			resu = pstat.executeQuery();
			if (resu.next()) {
				user = getUser(resu);
			}
		} finally {
			if (resu != null) {
				resu.close();
			}
			if (pstat != null) {
				pstat.close();
			}
		}
		return user;
	}

	// 获取用户
	private User getUser(ResultSet resu) throws SQLException {
		User user = new User();
		user.setId(resu.getString("USER_ID"));
		user.setName(resu.getString("USER_NAME"));
		user.setPassword(resu.getString("PASSWORD"));
		user.setContact_tel(resu.getString("CONTACT_TEL"));
		user.setEmail(resu.getString("EMAIL"));
		user.setCreate_date(resu.getTimestamp("CREATE_DATE"));
		return user;
	}
}
 
Manager接口:
package gd.hz.manager;

import gd.hz.model.User;

public interface UserManager {
	public User findUser(String id) throws Exception;
}
 
Manager实现类:
package gd.hz.manager;

import java.sql.SQLException;

import gd.hz.dao.UserDAO;
import gd.hz.dao.UserDAOImpl;
import gd.hz.model.User;

public class UserManagerImpl implements UserManager {
	private UserDAO userDAO = null;

	public UserManagerImpl() {
		userDAO = new UserDAOImpl();
	}

	public User findUser(String id) throws SQLException {
		return userDAO.selUser(id);
	}
}
 
创建代理类:
package gd.hz.util;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;

//Manager代理类
public class TransctionProxy implements InvocationHandler {
	private Object obj = null;

	// obj:需要代理的类
	public Object newProxyInstance(Object obj) {
		this.obj = obj;
		return Proxy.newProxyInstance(this.obj.getClass().getClassLoader(),
				this.obj.getClass().getInterfaces(), this);
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		// 用于接收参数
		Object param = null;
		// 如果是以下方法开头,则代理事务
		if (method.getName().startsWith("add")
				|| method.getName().startsWith("modify")
				|| method.getName().startsWith("find")
				|| method.getName().startsWith("del")) {
			Connection conn = ConnectionManager.getConnection();
			try {
				// 手动提交事务
				ConnectionManager.benigTransction(conn);
				param = method.invoke(obj, args);
				// 提交事务
				ConnectionManager.endTransction(conn);
			} catch (Exception e) {
				// 回滚事务
				ConnectionManager.rollback(conn);
				if (e instanceof InvocationTargetException) {
					InvocationTargetException inv = (InvocationTargetException) e;
					throw inv.getTargetException();
				} else {
					throw new Exception("操作失败!");
				}
			} finally {
				// 还原状态
				ConnectionManager.recoverTransction(conn);
				ConnectionManager.close();
			}
		}
		return param;
	}
}
 
测试:
package gd.hz.util;

import gd.hz.manager.UserManager;
import gd.hz.manager.UserManagerImpl;
import gd.hz.model.User;

public class Test {
	public static void main(String[] args) throws Exception {
		TransctionProxy transctionProxy = new TransctionProxy();

		// //产生代理对象
		UserManager userManager = (UserManager) transctionProxy
				.newProxyInstance(new UserManagerImpl());
		User user = userManager.findUser("root");
		System.out.println("用户名:" + user.getName());
	}
}
 

 



已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [java 代理 threadlocal] 推荐:

java 使用动态代理 - ThreadLocal实现事务管理

- - ITeye博客
动态代理:JDK动态代理只能对实现了接口的类进入代理,采用JDK动态代理必须实现InvocationHandler接口,采用Proxy 类创建相应的代理类.. 下面使用Model2(MVC)使用代理事务查询用户基本信息,使用DB2数据库:. 建立表: create table T_USER (. constraint P_KEY_1 primary key (USER_ID) ); 初始化数据: insert into t_user(user_id, user_name, password) values('root', '系统管理员', 'root');.

POJO中使用ThreadLocal实现Java嵌套事务

- - ImportNew
大多嵌套事务都是通过EJB实现的,现在我们尝试实现对POJO的嵌套事务. 这里我们使用了ThreadLocal的功能. 所以内层事务或外层事务可以在不影响其他事务的条件下进行回滚或提交. 新建的事务嵌套在外层事务中. 如果内层事务完成(不论是回滚或是提交),外层的事务就可以进行回滚或提交,这样的操作并不会影响内层事务.

ThreadLocal介绍

- - ITeye博客
一、java.lang.ThreadLocal. 一个实例就是一个容器,所有可以访问到这个实例的线程都可以在这个容器中存储一个该线程独立使用的变量. 这个实例里面其实是一个Map结构的属性,存储以线程对象为KEY,变量为VALUE的数据. 二、ThreadLocal有这样几个方法:. 返回当前线程对应的那个变量.

正确理解ThreadLocal

- - Java - 编程语言 - ITeye博客
转自: http://www.iteye.com/topic/103804. 首先,ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的. 另外,说ThreadLocal使得各线程能够保持各自独立的一个对象,并不是通过ThreadLocal.set()来实现的,而是通过每个线程中的new 对象 的操作来创建的对象,每个线程创建一个,不是什么对象的拷贝或副本.

ThreadLocal的内存泄露

- - zzm
ThreadLocal的目的就是为每一个使用ThreadLocal的线程都提供一个值,让该值和使用它的线程绑定,当然每一个线程都可以独立地改变它绑定的值. 如果需要隔离多个线程之间的共享冲突,可以使用ThreadLocal,这将极大地简化你的程序.. 关于的ThreadLocal更多内容,请参考《 ThreadLocal》.

java 动态代理(Proxy)

- - BlogJava_首页
动态代理可以提供对另一个对象的访问,同时隐藏实际对象的具体事实,代理对象对客户隐藏了实际对象. 动态代理可以对请求进行其他的一些处理,在不允许直接访问某些类,. 或需要对访问做一些特殊处理等,这时候可以考虑使用代理. 目前 Java 开发包中提供了对动态代理的支持,但现在只支持对接口的实现. 主要是通过 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口.

JAVA之JDK动态代理

- - Java - 编程语言 - ITeye博客
在Java的java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过这个类和接口,可以生成JDK动态代理类或动态代理对象. Proxy提供了用于创建动态代理类和代理对象的静态方法,它也是所有动态代理类的父类,如果在程序中为一个或多个接口动态的生成实现类,就可以使用Proxy来创建动态代理类,.

(转)ThreadLocal的内存泄漏问题

- - 编程语言 - ITeye博客
原文:http://www.godiscoder.com/?p=479. 在最近一个项目中,在项目发布之后,发现系统中有内存泄漏问题. 表象是堆内存随着系统的运行时间缓慢增长,一直没有办法通过gc来回收,最终于导致堆内存耗尽,内存溢出. 开始是怀疑ThreadLocal的问题,因为在项目中,大量使用了线程的ThreadLocal保存线程上下文信息,在正常情况下,在线程开始的时候设置线程变量,在线程结束的时候,需要清除线程上下文信息,如果线程变量没有清除,会导致线程中保存的对象无法释放.

ThreadLocal解决dateFormat多线程错误

- - 研发管理 - ITeye博客
出处  http://www.blogjava.net/killme2008/archive/2011/07/10/354062.html.     上周在线上系统发现了两个bug,值得记录下查找的过程和原因. 以后如果还有查找bug比较有价值的经历,我也会继续分享.     第一个bug的起始,是在线上日志发现一个频繁打印的异常——java.lang.ArrayIndexOutOfBoundsException.

Java事务(五) - 使用动态代理

- - CSDN博客推荐文章
在 上一篇博文中, 我们使用模板模式进行事务管理, 代码看起来已经很简洁了, 但是还是不太完美, . 我们依然需要在service层编写和事务相关的代码, 即我们需要在service层宗声明一个TransactionTemplate.. 本篇文章中, 我们将使用Java提供的动态代理来完成事务处理, 你将看到无论在service层还是在dao层都不会.