package bean.parterdesign.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public class Client { /** * @param args */ public static void main(String[] args) { //RealSubject 是接口Subject 的实现类 RealSubject rs = new RealSubject(); // 在这里指定被代理类 InvocationHandler ds = new DynamicSubject(rs); // 初始化代理类 //实现类的相关信息 ClassLoader rsClassLoader = RealSubject.class.getClassLoader(); Class[] rsInterfaces = RealSubject.class.getInterfaces(); //生成RealSubject 的代理类, 并执行 Subject subject = (Subject) Proxy.newProxyInstance( rsClassLoader,rsInterfaces, ds); subject.request(); System.out.println("======动态代理类====" + subject.getClass().getName() ); /*// 以下是分解步骤 * Class c = Proxy.getProxyClass(cls.getClassLoader(),cls.getInterfaces()) ; * Constructor ct=c.getConstructor(new Class[]{InvocationHandler.class}); * Subject subject =(Subject) ct.newInstance(new Object[]{ds}); */ Class c = Proxy.getProxyClass(rsClassLoader,rsInterfaces) ; System.out.println( c.getName() ); System.out.println("===== 动态代理类实现的接口==" + c.getInterfaces()[0].getName() ); } }
RealSubject 的代码:
package bean.parterdesign.proxy; public class RealSubject implements Subject { public RealSubject() { } //提交数据更新操作 public void request() { System.out.println("UPDATE DATABASE From real subject."); } }
DynamicSubject(InvocationHandler接口的实现类) 的代码:
Proxy根据InvocationHandler接口的实现类中的内容生成最后供用户调用的Subject接口
//生成RealSubject 的代理类
Subject subject = (Subject) Proxy.newProxyInstance( rsClassLoader,rsInterfaces, ds);
package bean.parterdesign.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class DynamicSubject implements InvocationHandler { private Object sub; // sub 必须是一个接口的实现类 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //为啥要设置自动提交为false ?很多数据库驱动是自动提交的 System.out.println("设置 Object sub 中的CONNECTION自动提交为false , connect before calling " + method); try { method.invoke(sub, args); } catch (Exception e) { System.out.println("发生异常时进行数据回滚 , " + method); } System.out.println("没有异常时,可以提交 after calling " + method); return null; } public DynamicSubject() { } public DynamicSubject(Object obj) { sub = obj; } }
--------------------------------------------------------------------
DynamicSubject 中我们可以模拟数据库操作;实现事务管理;
初级开发者会犯一个错误:直接从SPRING中配置的DATASOURCE中取得CONNECT数据库连接,这样会导致事务失效;
因为你取得的连接的AUTOCOMMIT 是TRUE ;这样事务就没法交给SPRING进行管理啦。
用代理的作用其实就是控制CONNECT数据库连接,通过代理我们可以控制数据库操作的提交和回滚;
另外早期的SPRING事务管理必须是基于接口的,当现在改变啦!为啥必须基于接口?看看这段代码:
Proxy根据InvocationHandler接口的实现类中的内容生成最后供用户调用的Subject接口 ,
newProxyInstance 中有个参数必须是接口的集合,这个就是原因
//生成RealSubject 的代理类 Subject subject = (Subject) Proxy.newProxyInstance( rsClassLoader,rsInterfaces, ds);