日期:2014-05-20  浏览次数:20775 次

动态代理的内部实现。例子:数据库连接。
Java code

/**
 * 单例模式,通过DBPool连接池获取数据库连接
 * @author shi
 */
public class JdbcUtils {
    
    private static Logger logger = Logger.getLogger(JdbcUtils.class);
    
    //简单的数据库连接池
    private static DataSource dataSource = new DBPool();
    private static JdbcUtils instance; 
    
    //构造函数私有化,为实现单例
    private JdbcUtils() {
    }
    
    //注意:"锁"的方式,以及第二次"null"的判断(仔细思考:若两个线程同时到达)
    public static JdbcUtils getInstance() {
        if(instance == null) {
            synchronized (JdbcUtils.class) {
                if(instance == null) {
                    instance = new JdbcUtils();    
                }
            }
        }
        logger.info("成功获取JdbcUtils实例");
        return instance;
    }
    
    //返回连接Connection
    public Connection getConnetion() throws SQLException {
        return dataSource.getConnection();
    
    }
    
    //释放资源
    public void free(ResultSet rs, Statement st, Connection conn) {
        try {
            if(rs != null) rs.close();
        } catch (SQLException e) {
            throw new JdbcException(e.getMessage());
        } finally {
            try {
                if(st != null)st.close();
            } catch (SQLException e) {
                throw new JdbcException(e.getMessage());
            } finally {
                try {
                    if(conn != null) conn.close();
                } catch (SQLException e) {
                    throw new JdbcException(e.getMessage());
                }
            }
        }
    }    
}
----------------------------------------
/**
 * 数据库连接池
 * @author shi
 */
public class DBPool{
    private static Logger logger = Logger.getLogger(DBPool.class);
    private static LinkedList<Connection> connectionPool;
    private static int currentCount;
    private        Selec


上面是利用动态代理的一个小例子。但“动态代理”的内部机制是怎样实现的呢?还是通过“反射”吗?请大家指点。

------解决方案--------------------
Java code

我做了个测试 调用ProxyGenerator.generateProxyClass(proxyName, interfaces);方法得到字节码 写到文件中(.class文件) 然后通过JD反编译 得到代理类(.java文件)

这个类是这样的
public final class MyProxyClass extends Proxy implements MyInterface
有一个构造方法
public MyProxyClass(InvocationHandler paramInvocationHandler)
    throws {
    super(paramInvocationHandler);
  }



所以我们通常用动态代理是这么用的:

写一个类,比如名字叫MyHandler,实现InvocationHandler接口.
然后把MyHandler对象作为参数传给Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);这个方法.
这个方法会调用ProxyGenerator.generateProxyClass(proxyName, interfaces);方法生成一个代理类.然后通过反射调用上面那个构造方法进行实例化,参数就是自己写的MyHandler的对象.
而这个代理类的任何方法实际上都是调用这个MyHandler的invoke方法,只是不同方法的参数不同.

所以无论你调用什么方法,实际上都在调用你写的invoke方法.
这样你就可以在invoke方法里自由发挥,前插后插,随便你怎么插,这就是AOP.

------解决方案--------------------
探讨
引用:
谁说的动态代理就是反射啊?


我说肯定用到了反射 没说只用了反射

动态代理的本质就在这个方法里
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                    proxyName, interfaces);
这个proxyName难道不是反射得到的吗?

然后通过这个名字和接口生成java源代码 编译成字节码文件 调入虚拟机 实例化 返回对象

就这么简单