代理模式(了解)
生活中: (1)自己不方便做一些事情,例如:去国外 找代购 (2)自己没资源,例如:找女朋友 找红娘
Java中: (1)当前这个类做一些事情,不太方便,因为这个事情是多变,重复的,我可以交给代理 例如:项目经理说,在测试环境,即开发阶段(不是生产环境,上线就是生产环境),测试一下每一个方法的运行时间,并且记录方法运行的日志 开发完了,项目经理说,把那些代码都去掉。
interface DAO{ void add(); /* void update(); void delete(); void select();*/ } class UserDAOImpl implements DAO{ @Override public void add() { System.out.println("add方法开始执行"); long start = System.currentTimeMillis(); System.out.println("添加用户"); long end = System.currentTimeMillis(); System.out.println("运行时间:" + (end-start)); System.out.println("add方法执行结束"); } } class GoodsDAOImpl implements DAO{ @Override public void add() { System.out.println("add方法开始执行"); long start = System.currentTimeMillis(); System.out.println("添加商品"); long end = System.currentTimeMillis(); System.out.println("运行时间:" + (end-start)); System.out.println("add方法执行结束"); } }问题:有很多代码重复,并且现在若是在开发环境下,开发完后,要将这些代码去掉,需要修改代码,这些都不是业务的实际代码,代理来做
1、代理模式 (1)主题接口:要求代理类与被代理类实现同一个接口,例如:DAO接口 (2)被代理者 (3)代理者: 必须持有被代理者的引用
2、静态代理模式 缺点:一个代理类只能替一个代理主题(接口)代理工作 interface DAO{ void add(); /* void update(); void delete(); void select();*/ } class UserDAOImpl implements DAO{ @Override public void add() { // System.out.println("add方法开始执行"); // long start = System.currentTimeMillis(); System.out.println("添加用户"); // long end = System.currentTimeMillis(); // System.out.println("运行时间:" + (end-start)); // System.out.println("add方法执行结束"); } } class GoodsDAOImpl implements DAO{ @Override public void add() { // System.out.println("add方法开始执行"); // long start = System.currentTimeMillis(); System.out.println("添加商品"); // long end = System.currentTimeMillis(); // System.out.println("运行时间:" + (end-start)); // System.out.println("add方法执行结束"); } } class DAOProxy implements DAO{ private DAO dao;//持有被代理者的引用,因为核心业务逻辑仍然交给被代理者自己完成 public DAOProxy(DAO dao) { super(); this.dao = dao; } public void add(){ System.out.println("add方法开始执行"); long start = System.currentTimeMillis(); // System.out.println("添加商品");//核心业务逻辑交给被代理者自己玩 dao.add(); long end = System.currentTimeMillis(); System.out.println("运行时间:" + (end-start)); System.out.println("add方法执行结束"); } } @Test public void test01(){ //new UserDAOImpl()被代理者对象 //new DAOProxy(x)代理者对象 DAO d = new DAOProxy(new UserDAOImpl()); d.add(); }这样写也可以撇开代理模式完成业务
public class TestAgent { public static void main(String[] args) { GoodsDAOImpl dao = new GoodsDAOImpl(); dao.add(); }若是再增加一个接口 MyInter,有自己的实现类,要求实现与之前那个实现类一样的代理。原有的代理类就不能替它代理,就得还重新创建一个代理类,麻烦且重复,用动态代理
interface MyInter{ void test(); } class Impl implements MyInter{ @Override public void test() { } 3、动态代理模式 与反射有关 动态代理模式:主要用在Spring框架中 优点:一个代理工作处理器,可以替多个代理主题(接口)代理工作,只有代理工作内容一样就可以。 需要: (1)编写一个代理工作处理器的类,这个类必须实现一个接口InvocationHandler (2)用JDK中提供了一个Proxy类,来创建代理类的对象 new ProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) 参数一:被代理者的类加载器对象 参数二:被代理者实现的接口们 参数三:代理者替被代理者要完成的工作的处理器对象 (3)调用方法 //主题1 interface A{ void a(); } //被代理者1 class AImpl implements A{ @Override public void a() { System.out.println("a方法被执行"); } } //主题2 interface B{ void b(); } //被代理者2 class BImpl implements B{ @Override public void b() { System.out.println("b方法被执行"); } } //接口是定义好的 class Handler implements InvocationHandler{ private Object target;//被代理者对象 public Handler(Object target) { super(); this.target = target; } /* * 参数一:代理类的对象 * 参数二:被代理者要执行的方法 * 参数三:被代理者要执行的方法需要的实参列表 * 这个方法不是程序调用的,是一会执行代理类对象的方法时自动调用 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //proxy:代理者自己 System.out.println(method.getName() + "方法开始执行");//执行的方法的名字,可能是add可能delete等 long start = System.currentTimeMillis(); // method.invoke(obj, args);//obj是要求写被代理者对象,需要传进来,构造方法初始化时传进来 Object value = method.invoke(target, args); long end = System.currentTimeMillis(); System.out.println("运行时间:" + (end-start)); System.out.println(method.getName() + "方法执行结束"); return value; } } @Test public void test01() { AImpl a = new AImpl();//被代理者 ClassLoader loader = a.getClass().getClassLoader();//被代理者的类加载器对象 Class<?>[] interfaces = a.getClass().getInterfaces();//被代理者的实现接口们 Handler h = new Handler(a);//代理者替被代理者要完成的工作的处理器对象 A proxy = (A) Proxy.newProxyInstance(loader, interfaces, h); proxy.a(); }上是替A代理,若是替B代理
@Test public void test02() { BImpl b = new BImpl();//被代理者 ClassLoader loader = b.getClass().getClassLoader(); Class<?>[] interfaces = b.getClass().getInterfaces(); Handler h = new Handler(b); B proxy = (B) Proxy.newProxyInstance(loader, interfaces, h); proxy.b(); } //其他代码不变