【java】动态代理+ThreadLocal实现数据源及事务管理

本文探讨如何使用Java动态代理和ThreadLocal解决数据源及事务管理问题。通过分析难点,如连接对象close方法的改写和多线程下Connection的安全,介绍了一种模拟连接池的方法,并利用ThreadLocal保证每个线程拥有独立的Connection。最后提供了源码下载链接。
摘要由CSDN通过智能技术生成

一、前言

        小demo只是思想的一个简单实现,距离用在生产环境还有一定距离,只是五一劳动节放假宅在家用来锻炼一下思维,不严谨的地方还望见谅。想要看更完整的示例代码,请查看mybatis源码,pooled类的实现。


二、难点分析

        JDBC数据源的规范来自java.sql.DataSource接口,里面就一个方法getConnection的两个重载(数据源的思想也已经很普遍了,这里就不再赘述,需要了解的请自行查找),所以数据源的首要任务就是提供数据库连接对象Connection,这个太容易实现了,毫无难点可言,但是获得了连接,使用完之后是需要关闭的,此时连接的关闭不是释放资源,而是将连接对象还回数据库连接池。

        难点一:连接对象的关闭不是释放资源,而是将连接对象还回数据库连接池——close方法的改写

        上面的描述太过随意浮躁,没有体现难点之所在。java.sql.Connection作为数据库连接的规范接口而存在,他规定了连接对象的两大功能,一是和数据库建立链接,而是为此链接创建执行对象,不同的数据库厂商实现有不同,但是规范都得遵守,无论是mysql还是Oracle,他们提供的数据库驱动包中对java.sql.Connection的实现都要按照规则来,否则程序员们就不乐意了,不好进行开发、不好进行维护啊。那就看一下规范,java.sql.Connection接口中对close方法的描述。

 /**
     * Releases this <code>Connection</code> object's database and JDBC resources
     * immediately instead of waiting for them to be automatically released.
     * <P>
     * Calling the method <code>close</code> on a <code>Connection</code>
     * object that is already closed is a no-op.
     * <P>
     * It is <b>strongly recommended</b> that an application explicitly
     * commits or rolls back an active transaction prior to calling the
     * <code>close</code> method.  If the <code>close</code> method is called
     * and there is an active transaction, the results are implementation-defined.
     * <P>
     *
     * @exception SQLException SQLException if a database access error occurs
     */
    void close() throws SQLException;
        是不是粗大事了?不是等待啊,是立即释放链接对象和JDBC资源,很强烈的语气助词“immediately”和“strongly”。释放资源,也就是关闭和数据库的链接,不要Connection对象了,口说无凭,直接看mysql驱动包中close方法的实现。

        附送更详细的小文链接一枚:点击打开链接

/**
 * In some cases, it is desirable to immediately release a Connection's
 * database and JDBC resources instead of waiting for them to be
 * automatically released (cant think why off the top of my head) <B>Note:</B>
 * A Connection is automatically closed when it is garbage collected.
 * Certain fatal errors also result in a closed connection.
 * 
 * @exception SQLException
 *                if a database access error occurs
 */
public void close() throws SQLException {
	synchronized (getConnectionMutex()) {
		if (this.connectionLifecycleInterceptors != null) {
			new IterateBlock<Extension>(this.connectionLifecycleInterceptors.iterator()) {
				void forEach(Extension each) throws SQLException {
					((ConnectionLifecycleInterceptor)each).close();
				}
			}.doForAll();
		}
	
		realClose(true, true, false, null);
	}
}

/**
 * Closes connection and frees resources.
 * 
 * @param calledExplicitly
 *            is this being called from close()
 * @param issueRollback
 *            should a rollback() be issued?
 * @throws SQLException
 *             if an error occurs
 */
public void realClose(boolean calledExplicitly, boolean issueRollback,
		boolean skipLocalTeardown, Throwable reason) throws SQLException {
	SQLException sqlEx = null;

	if (this.isClosed()) {
		return;
	}
	
	this.forceClosedReason = reason;
	
	try {
		if (!skipLocalTeardown) {
			if (!getAutoCommit() && issueRollback) {
				try {
					rollback();
				} catch (SQLException ex) {
					sqlEx = ex;
				}
			}

			reportMetrics();

			if (getUseUsageAdvisor()) {
		
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值