Java 代理模式

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 }
原文地址:https://www.cnblogs.com/zsy-code/p/13877724.html