JAva:ダイナミックエージェント


動的エージェントとは?既存のオブジェクトを変更する方法、制御方法の実行、または前のアクティブな実行を実行した後に追加の操作を行います.特定のクラスProxyはnewProxyInstanceという方法で、指定したインタフェースエージェントのインスタンスを返します.
新ProxyInstance(クラス・ローダ、エージェントが実装するインタフェースを指定します.プロセッサ・オブジェクトは、エージェント・オブジェクトを呼び出す任意の方法でinvokeメソッドを呼び出します.この方法では追加の操作ができます)
Object invoke(Object proxj,Method,Object[]arg 0)-エージェントオブジェクト-エージェントを実装する方法-メソッドパラメータ-戻り値がこのメソッドで返されるもののインスタンス
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();
    }

}