23种设计模式之代理模式(动态代理)

一:什么是动态代理:java

  利用反射机制在运行时建立代理类。接口、被代理类不变。程序员

二:动态代理和静态代理的不一样:ide

  一、静态代理的代理类是程序员事先写好的函数

  二、动态代理的代理类是在程序运行时动态生成的this

三:动态代理分为两大类:spa

  一、基于接口的动态代理代理

  二、基于类的动态代理日志

四:动态代理的三种实现方式:code

  一、基于接口--->JDK动态代理 (JAVA原生的)(咱们在这里使用)对象

  二、基于类--->cglib (本身查阅资料作了解)

  三、java字节码实现---> javassist (查资料了解)

五:在使用动态代理以前,首先了解两大类

  一、Proxy  (代理)

  二、InvocationHandler  (调用处理程序)

六:动态代理代码展现  (房东出租房子案例)

  一、建立一个抽象角色

1 //租房的接口      (抽象角色)
2 
3 public interface Rent {
4 
5     //出租的方法
6     void rent();
7 
8 }

  二、建立真实角色,实现抽象角色接口

1 //房东 要出租房子   (真实的角色)
2 
3 public class Host implements Rent {
4     @Override
5     public void rent() {
6         System.out.println("房东要出租房子");
7     }
8 }

  三、首先,咱们构建一个类来实现InvocationHandler接口           

 1 //动态生成代理
 2 
 3 public class ProxyInvocationHandler implements InvocationHandler {
 4 
 5     //被代理的接口
 6     private Rent rent;
 7 
 8     public void setRent(Rent rent) {
 9         this.rent = rent;
10     }
11 
12     //    Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
13 //            new Class<?>[] { Foo.class },
14 //            handler);
15 
16     //生成获得代理类   (经过Proxy类的静态方法newProxyInstance返回一个接口的代理实例。针对不一样的代理类,传入相应的代理程序控制器InvocationHandler)
17     public Object getProxy(){
18         return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this);
19 
20     }
21 
22     //处理代理实例,并返回结果
23     @Override
24     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
25 
26         //动态代理的本质,就是使用反射机制实现!
27         seeHouse();
28         Object result = method.invoke(rent, args);
29         fare();
30         return result;
31     }
32 
33     public void seeHouse(){
34         System.out.println("中介带看房子!");
35     }
36     public void fare(){
37         System.out.println("收中介费!");
38     }
39 }

  四、执行动态代理

 1 //执行动态代理,实现租房方法
 2 
 3 public class Client {
 4     public static void main(String[] args) {
 5         //真实角色
 6         Host host = new Host();
 7 
 8         //代理角色,如今没有
 9         ProxyInvocationHandler pih = new ProxyInvocationHandler();
10         //经过调用程序来处理咱们要调用的接口对象!
11         pih.setRent(host);
12 
13         Rent proxy = (Rent) pih.getProxy();   //这里的proxy是动态生成的,咱们并无写!
14         //调用租房方法
15         proxy.rent();
16 
17     }
18 }

  五、输出结果

七:动态代理的具体步骤

    一、经过实现 InvocationHandler 接口建立本身的调用处理器;

    二、经过为 Proxy 类指定 ClassLoader 对象和一组 interface 来建立动态代理类;

    三、经过反射机制得到动态代理类的构造函数,其惟一参数类型是调用处理器接口类型;

    四、经过构造函数建立动态代理类实例,构造时调用处理器对象做为参数被传入。

八:动态代理的好处

    一、可使真实角色的操做更加纯粹!不用去关注一些公共的业务

    二、公共业务就交给代理角色!实现了业务的分工!  

    三、公共业务发生扩展的时候,方便集中管理

    四、一个动态代理类代理的是一个接口,通常就是对应的一类业务

    五、一个动态代理类能够代理多个类,只要是实现了同一个接口便可

九:根据上述的动态代理实现机制,咱们能够衍生出一个万能的动态代理类

 1 //万能的动态代理类
 2 
 3 public class ProxyInvocationHandler implements InvocationHandler {
 4 
 5     //被代理的接口
 6     private Object target;
 7 
 8     public void setTarget(Object target) {
 9         this.target = target;
10     }
11 
12     //    Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
13 //            new Class<?>[] { Foo.class },
14 //            handler);
15 
16     //生成获得代理类
17     public Object getProxy(){
18         return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
19 
20     }
21 
22     //处理代理实例,并返回结果
23     @Override
24     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
25 
26         //动态代理的本质,就是使用反射机制实现!
27         log(method.getName());
28         Object result = method.invoke(target, args);
29         return result;
30     }
31 
32     //根据不一样业务须要,建立不一样的扩展方法 (此处为打印日志)
33     public void log(String msg){
34         System.out.println("执行了"+msg+"方法!");
35     }
36 }

执行动态代理:

 1 //执行动态代理
 2 
 3 public class Client {
 4     public static void main(String[] args) {
 5         //真实角色
 6         UserServiceImpl userService = new UserServiceImpl();
 7 
 8         //代理角色,不存在
 9         ProxyInvocationHandler pih = new ProxyInvocationHandler();
10 
11         //设置要代理的对象
12         pih.setTarget(userService);
13 
14         //动态生成代理类
15         UserService proxy = (UserService) pih.getProxy();
16 
17         proxy.update();
18 
19     }
20 }

      注:抽象角色、真实角色 的实际代码此处省略(与静态代理实现步骤同样)

        【咱们可根据不一样的业务需求,套用万能动态代理模板便可】

相关文章
相关标签/搜索