1、什么是代理
代理是一种设计模式,它的核心思想,是将对目标的访问转移到代理对象上。这样做的好处就是,目标对象在不改变代码的情况下,可以通过代理对象加一些额外的功能。这是一种编程思想,在不改变原有代码的情况下,通过代理增加一些扩展功能。
代理过程如图所示,用户访问代理对象,代理对象通过访问目标对象,来达到用户访问目标对象的目的。
代理模式包含以下三个角色:
--| ISubject:接口对象,目标对象和代理对象共用的接口
--| TargetSubject:目标对象,实现共用的接口
--| Proxy:代理对象,内部含有对目标对象TargetSubject的引用,从而可以操作真实对象。代理对象提供与目标对象相同的接口,以便在任何时刻都能代替目标对象。同时,代理对象可以在执行目标对象操作时,附加其他的操作,相当于对真实对象进行封装。
常见的代理模式分为静态代理和动态代理,动态代理在Java中的实现分为JDK动态代理和cglib代理。
2、静态代理
1)共用接口对象
1 package proxy; 2 3 public interface playMovie { 4 void play(); 5 }
2)目标对象,实现共用的接口
1 package proxy; 2 3 public class RealMovie implements playMovie{ 4 5 @Override 6 public void play() { 7 System.out.println("电影开始播放了"); 8 } 9 }
3)代理对象
1 package proxy; 2 3 public class ProxyMovie implements playMovie{ 4 RealMovie rm; 5 6 public ProxyMovie(RealMovie rm) { 7 super(); 8 this.rm = rm; 9 } 10 11 public void guanggao() { 12 System.out.println("开始放广告了"); 13 } 14 15 @Override 16 public void play() { 17 // TODO Auto-generated method stub 18 guanggao(); 19 rm.play(); 20 System.out.println("电影结束了,散场了"); 21 } 22 23 }
4)客户端调用
1 package proxy; 2 3 public class ProxyTest { 4 public static void main(String[] args) { 5 RealMovie rm = new RealMovie(); 6 ProxyMovie pm = new ProxyMovie(rm); 7 pm.play(); 8 } 9 } 10 11 结果打印: 12 开始放广告了 13 电影开始播放了 14 电影结束了,散场了
静态代理,在不修改目标对象的情况下,可以通过代理对象做额外的扩展功能。但静态方法不是很灵活,如果目标接口的代码修改,目标对象和代理对象都需要修改。
动态代理在一定程度上避免这种情况,动态代理不需要代理对象实现目标接口,并且上在java 虚拟机的内存中动态的生成代理对象
3、动态代理(JDK代理)
Jdk的动态代理由Proxy这个类来生成,它有三个参数:
- ClassLoader loader,:指定当前目标对象使用类加载器,获取加载器的方法是固定的
- Class<?>[] interfaces,:目标对象实现的接口的类型,使用泛型方式确认类型
- InvocationHandler h:事件处理,执行目标对象的方法时,会触发事件处理器的方法,会把当前执行目标对象的方法作为参数传入
1 public static Object newProxyInstance(ClassLoader loader, 2 Class<?>[] interfaces, 3 InvocationHandler h) 4 throws IllegalArgumentException 5 {}
使用步骤如下:
1)共用接口对象
1 package proxy.jdkproxy; 2 3 public interface Subject { 4 public void doSomething() ; 5 }
2)目标对象,实现接口
1 package proxy.jdkproxy; 2 3 public class RealSubject implements Subject{ 4 5 @Override 6 public void doSomething() { 7 System.out.println("目标对象:do Something"); 8 } 9 10 }
3)代理对象
1 package proxy.jdkproxy; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5 6 public class ProxyFactory implements InvocationHandler{ 7 private Object proxied; 8 9 public ProxyFactory(Object proxied) { 10 this.proxied = proxied; 11 } 12 13 @Override 14 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 15 System.out.println("前置增强处理:yoho"); 16 Object obj =method.invoke(proxied, args); 17 System.out.println("后置增强处理:lalala"); 18 return obj; 19 } 20 21 }
4)客户端调用
1 package proxy.jdkproxy; 2 3 import java.lang.reflect.Proxy; 4 5 public class ProxyClient { 6 public static void main(String[] args) { 7 Subject rs = new RealSubject(); 8 Subject proxyOfrs = (Subject)Proxy.newProxyInstance(Subject.class.getClassLoader(), 9 new Class[] {Subject.class}, new ProxyFactory(rs)); 10 System.out.println(proxyOfrs); 11 12 proxyOfrs.doSomething(); 13 } 14 }