java:动态代理

啥叫动态代理?
用来修改已经具有的对象的方法,控制方法执行,或者执行之前活执行之后做一些额外的操作。
具体类
Proxy
通过newProxyInstance这个方法,返回一个指定的接口代理实例

newProxyInstance(类加载器,指定代理实现的那些接口。处理器对象当调用代理对象的任何方法都会调用invoke方法,这个方法中可以做一些额外的操作)

Object invoke(Object proxj,Method method,Object[]arg0)
–代理对象
-实现代理的方法
–方法参数
—返回值为这个方法要返回的东西
实例

package com.twj.util;

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

import javax.sql.DataSource;

import org.apache.commons.dbutils.DbUtils;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class TransactionManager {
    private TransactionManager() {
    }
    //--数据源,整个程序中都只有这一个数据源
    private static DataSource source = new ComboPooledDataSource();

    //--是否开启事务的标记
    private static ThreadLocal<Boolean> isTran_local = new ThreadLocal<Boolean>(){
        @Override
        protected Boolean initialValue() {
            return false;//--最开始false,表明默认不开启事务
        }
    };
    //--保存真实连接的代理连接,改造过close方法
    private static ThreadLocal<Connection> proxyConn_local = new ThreadLocal<Connection>(){};
    //--保存真实连接
    private static ThreadLocal<Connection> realconn_local = new ThreadLocal<Connection>(){};

    /**
     * 开启事务的方法
     * @throws SQLException
     */
    public static void startTran() throws SQLException{
        isTran_local.set(true);//--设置事务标记为true
        final Connection conn = source.getConnection();//--创建连接,所有当前线程中的数据库操作都基于这个conn
        conn.setAutoCommit(false);//--开启事务
        realconn_local.set(conn);//--为了方便后续关闭连接,将这个连接保存起在当前线程中

        //--由于一个事务需要执行多条sql,每个sql执行过后都关闭连接,这样一来后续的sql没法执行,所以这个地方法改造close方法,使他不能关闭连接
        Connection proxyConn = (Connection) Proxy.newProxyInstance(conn.getClass().getClassLoader(), conn.getClass().getInterfaces()
            , new InvocationHandler(){

                public Object invoke(Object proxy, Method method,
                        Object[] args) throws Throwable {
                    if("close".equals(method.getName())){
                        return null;
                    }else{
                        return method.invoke(conn, args);
                    }
                }

        });

        proxyConn_local.set(proxyConn);
    }

    /**
     * 提交事务
     */
    public static void commit(){
        DbUtils.commitAndCloseQuietly(proxyConn_local.get());
    }

    /**
     * 回滚事务
     */
    public static void rollback(){
        DbUtils.rollbackAndCloseQuietly(proxyConn_local.get());
    }

    /**
     * 这个方法应该做到:
     *      如果没有开启过事务,则返回最普通的数据源
     *      如果开启过事务,则返回一个改造过getConnection方法的数据源,这个方法改造后每次都返回同一个开启过事务的Connection
     * @return
     * @throws SQLException 
     */
    public static DataSource getSource() throws SQLException{
        if(isTran_local.get()){//--如果开启过事务,则返回改造的DataSource,改造为每次调用getConnection都返回同一个开启过事务的Conn


            return (DataSource) Proxy.newProxyInstance(source.getClass().getClassLoader(), source.getClass().getInterfaces()
                ,new InvocationHandler(){
                    public Object invoke(Object proxy, Method method,
                            Object[] args) throws Throwable {
                        if("getConnection".equals(method.getName())){
                            return proxyConn_local.get();
                        }else{
                            return method.invoke(source, args);
                        }
                    }
            });

        }else{//--没有开启过事务,返回普通的数据源
            return source;
        }

    }

    /**
     * 释放资源 
     */
    public static void release(){
        DbUtils.closeQuietly(realconn_local.get());//--之前连接是没有关闭的在release的时候真正的关闭连接
        realconn_local.remove();
        proxyConn_local.remove();
        isTran_local.remove();
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值