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

一:什么是动态代理:

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

二:动态代理和静态代理的不同:

1、静态代理的代理类是程序员事先写好的

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

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

1、基于接口的动态代理

2、基于类的动态代理

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

1、基于接口—>JDK动态代理 (JAVA原生的)(我们在这里使用)

2、基于类—>cglib (自己查阅资料做了解)

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

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

1、Proxy (代理)

2、InvocationHandler  (调用处理程序)

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

1、创建一个抽象角色

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

2、创建真实角色,实现抽象角色接口

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

3、首先,我们构建一个类来实现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 }

4、执行动态代理

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 }

5、输出结果

在这里插入图片描述

七:动态代理的具体步骤

1、通过实现 InvocationHandler 接口创建自己的调用处理器;

2、通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;

3、通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;

4、通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。

八:动态代理的好处

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

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

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

4、一个动态代理类代理的是一个接口,一般就是对应的一类业务

5、一个动态代理类可以代理多个类,只要是实现了同一个接口即可

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

**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 }

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

【我们可根据不同的业务需求,套用万能动态代理模板即可】

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值