您的位置:首页 > 编程语言 > Java开发

java:动态代理

2016-05-27 10:14 309 查看
啥叫动态代理?

用来修改已经具有的对象的方法,控制方法执行,或者执行之前活执行之后做一些额外的操作。

具体类

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();
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 处理器