通过一个工具类更深入理解动态代理和Threadlocal
来源:互联网 发布:软件项目进度表 excel 编辑:程序博客网 时间:2024/06/05 02:01
动态代理和Threadlocal
这样的话就可以两全其美,我重点想说的是,两个动态代理同时运行时,执行过程是怎样的?
import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.sql.Connection;import javax.sql.DataSource;import com.mchange.v2.c3p0.ComboPooledDataSource;public class DaoUtils {private static DataSource source=new ComboPooledDataSource();private DaoUtils(){}//普通情况/*public static DataSource getSource(){return source;}*//** * 改造此方法,在调用这个方法时检查,当前线程是否开启过事务 * 如果没有开启事务,返回的是最普通的数据源 * 如果开启过过事务,则返回改造过的数据源--改造底层获取连接的getConnection */public static DataSource getSource(){if(TransactionManager.hasStarTran()){//开启过事务,返回一个改造getConnection--每次返回都开启了事务的的连接,此方法每次都返回,当前线程DataSource proxy= (DataSource) Proxy.newProxyInstance(source.getClass().getClassLoader(), source.getClass().getInterfaces(), new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//if("getconnction".equals(method.getName())){if("getConnection".equals(method.getName())){//当前调用getConnection方法,使它每次都返回当前的线程变量中保存当前线程中使用开启事务的连接final Connection conn=TransactionManager.getconn();Connectionproxy2= (Connection) Proxy.newProxyInstance(conn.getClass().getClassLoader(), conn.getClass().getInterfaces(), new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if("close".equals(method.getName())){return null;//什么也不做}else{return method.invoke(conn, args) ;}}});return proxy2;}else{return method.invoke(source, args);}}}); return proxy;}else{//如果没有开启事务,就返回return source;}}public static Connection conn(){try {return source.getConnection();} catch (Exception e) {e.printStackTrace();throw new RuntimeException(e);}}}
事务的工具类:
import java.sql.Connection;import javax.sql.DataSource;import org.apache.commons.dbutils.DbUtils;public class TransactionManager {/*因为存在多个线程共用一个连接,一个ThreadLocal代表一个变量,故其中里只能放一个数据,你有两个变量都要线程范围内共享,则要定义两个ThreadLocal对象。如果有一个百个变量要线程共享呢?那请先定义一个对象来装这一百个变量,然后在ThreadLocal中存储这一个对象。*//*private static ThreadLocal<Connection> conn_local=new ThreadLocal<Connection>(){protected Connection initialValue() {return DaoUtils.conn();//连接数据库}};*/private static ThreadLocal<Connection> conn_local=new ThreadLocal<Connection>(){@Overrideprotected Connection initialValue() {return DaoUtils.conn();};};//判断是否开启事务private static ThreadLocal<Boolean> hasStarTran_local=new ThreadLocal<Boolean>(){@Overrideprotected Boolean initialValue() {return false;};};private TransactionManager(){}//开启事务public static void startTran(){try {conn_local.get().setAutoCommit(false);//开启事务hasStarTran_local.set(true);} catch (Exception e) {e.printStackTrace();throw new RuntimeException(e);}}//判断是否开启事务public static boolean hasStarTran(){return hasStarTran_local.get();}//提交事务public static void commit(){try {conn_local.get().commit();} catch (Exception e) {e.printStackTrace();throw new RuntimeException(e);}}//回滚事务public static void rollback(){try {conn_local.get().rollback();} catch (Exception e) {e.printStackTrace();throw new RuntimeException(e);}}public static Connection getconn(){return conn_local.get();}//释放连接public static void release(){DbUtils.closeQuietly(conn_local.get());conn_local.remove();hasStarTran_local.remove();}}
public class MyInvocationHandler implements InvocationHandler { // 目标对象 private Object target; /** * 构造方法 * @param target 目标对象 */ public MyInvocationHandler(Object target) { super(); this.target = target; } /** * 执行目标对象的方法 */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 在目标对象的方法执行之前 System.out.println("------------------before------------------"); // 执行目标对象的方法 Object result = method.invoke(target, args); // 在目标对象的方法执行之后 System.out.println("-------------------after------------------"); return result; } /** * 获取目标对象的代理对象 * @return 代理对象 */ public Object getProxy() { return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), target.getClass().getInterfaces(), this); } }
下面是动态代理的源码:类加载器,一大堆接口,还有就是代理的实现类
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException{ if (h == null) { throw new NullPointerException(); } /* * Look up or generate the designated proxy class. */ Class<?> cl = getProxyClass0(loader, interfaces); // stack walk magic: do not refactor /* * 调用它的构造函数指定调用处理程序。 */ try { final Constructor<?> cons = cl.getConstructor(constructorParams); final InvocationHandler ih = h; SecurityManager sm = System.getSecurityManager(); if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) { // create proxy instance with doPrivilege as the proxy class may // implement non-public interfaces that requires a special permission return AccessController.doPrivileged(new PrivilegedAction<Object>() { public Object run() { return newInstance(cons, ih); } }); } else { return newInstance(cons, ih); } } catch (NoSuchMethodException e) { throw new InternalError(e.toString()); } } private static Object newInstance(Constructor<?> cons, InvocationHandler h) { try { return cons.newInstance(new Object[] {h} ); } catch (IllegalAccessException | InstantiationException e) { throw new InternalError(e.toString()); } catch (InvocationTargetException e) { Throwable t = e.getCause(); if (t instanceof RuntimeException) { throw (RuntimeException) t; } else { throw new InternalError(t.toString()); } } } /** * Returns true if and only if the specified class was dynamically * generated to be a proxy class using the {@code getProxyClass} * method or the {@code newProxyInstance} method. * * <p>The reliability of this method is important for the ability * to use it to make security decisions, so its implementation should * not just test if the class in question extends {@code Proxy}. * * @param cl the class to test * @return {@code true} if the class is a proxy class and * {@code false} otherwise * @throws NullPointerException if {@code cl} is {@code null} */ public static boolean isProxyClass(Class<?> cl) { if (cl == null) { throw new NullPointerException(); } return proxyClasses.containsKey(cl); } /** * Returns the invocation handler for the specified proxy instance. * * @param proxy the proxy instance to return the invocation handler for * @return the invocation handler for the proxy instance * @throws IllegalArgumentException if the argument is not a * proxy instance */ public static InvocationHandler getInvocationHandler(Object proxy) throws IllegalArgumentException { /* * Verify that the object is actually a proxy instance. */ if (!isProxyClass(proxy.getClass())) { throw new IllegalArgumentException("not a proxy instance"); } Proxy p = (Proxy) proxy; return p.h; }进去ProxyGenerator类的静态方法generateProxyClass,这里是真正生成代理类class字节码的地方。你可以去你的web-info目录下的classes中看到用到动态代理的类,都会多出一个字节码文件。带$的,可以用ju-gui(反编译工具)看到,里面就是一个代理对象。public static byte[] generateProxyClass(final String name, Class[] interfaces) { ProxyGenerator gen = new ProxyGenerator(name, interfaces); final byte[] classFile = gen.generateClassFile(); // 如果saveGeneratedFiles的值为true,则会把所生成的代理类的字节码保存到硬盘上 if (saveGeneratedFiles) { java.security.AccessController.doPrivileged( new java.security.PrivilegedAction<Void>() { public Void run() { try { FileOutputStream file = new FileOutputStream(dotToSlash(name) + ".class"); file.write(classFile); file.close(); return null; } catch (IOException e) { throw new InternalError( "I/O exception saving generated file: " + e); } } }); } // 返回代理类的字节码 return classFile; }
0 0
- 通过一个工具类更深入理解动态代理和Threadlocal
- 用数组存对象-更深入理解类与对象
- 如何更深入的理解各种选择器
- 关于SpinLock的更深入理解
- 动态代理工具类
- 对viewstates的理解更深入了(1)
- 对viewstates的理解更深入了(2)
- CDialog与其对话资源绑定的更深入理解
- nyoj311-完全背包(01背包更深入理解)
- 静态代理和动态代理的理解
- 理解ThreadLocal和匿名类
- java 使用动态代理 和ThreadLocal实现事务管理实例
- 再更深入一点
- 我想更深入c++
- 通过代码组织,让你更好的理解和使用JDK动态代理
- 一个优雅的threadLocal工具类
- java动态代理和cglib动态代理的整合工具
- JavaAop动态代理工具类
- 黑马程序员——Java基础语法(中)
- Javascript继承之最佳实践
- ny 324 猴子吃桃问题
- Android 图片内存缓存
- Spring笔记之一 -- 简单入门讲解HelloWorld
- 通过一个工具类更深入理解动态代理和Threadlocal
- 网卡软中断绑定优化
- 关于支付宝接口整合的几个问题
- poj 2442
- [leetcode] Maximum Depth of Binary Tree
- eclipse快捷键汇总
- 友盟在线参数+自动更新升级SDK实现指定版本强制更新升级
- CodeForces 154B——Colliders
- 数据库 SQLite