代理模式(2):动态代理
一,动态代理介绍
- 动态代理和静态代理的角色都是一样,静态代理模式的代理类是我们提前写好的,而动态代理的类是动态生成的,其实动态代理与静态代理的本质一样,最终程序运行时都需要生成一个代理对象实例,通过它来完成相关增强以及业务逻辑,只不过静态代理需要硬编码的方式指定,而动态代理支持运行时动态生成这种实现方式。动态生成的好处很明显,在编码时,代理逻辑与业务逻辑互相独立,各不影响,没有侵入,没有耦合
二,与动态代理相关的两个类
- Interface InvocationHandler:该接口中仅定义了一个方法Object:invoke(Object obj,Method method,Object[] args)。在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,args为该方法的参数数组。这个抽象方法在代理类中动态实现
- Proxy:该类即为动态代理类,作用类似于上例中的ProxySubject,其中主要包含以下内容:
Protected Proxy(InvocationHandler h):构造函数,估计用于给内部的h赋值。
Static Class getProxyClass (ClassLoader loader,Class[] interfaces):获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组
三,代码实现动态代理
1,抽象角色
1 //抽象角色
2 public interface User {
3
4 public void add();
5
6 }
2,真实角色
1 //真实角色
2 public class UserImpl implements User {
3
4 public void add() {
5 System.out.println("这是一个add方法");
6 }
7
8 }
3,动态代理类生成的接口对象
1 import java.lang.reflect.InvocationHandler;
2 import java.lang.reflect.Method;
3 import java.lang.reflect.Proxy;
4
5 public class InvocationHandlerProxy implements InvocationHandler {
6
7 private User user;
8
9 public void setUser(User user) {
10 this.user = user;
11 }
12
13 //动态生成代理类
14 public Object getProxy(){
15 return Proxy.newProxyInstance(this.getClass().getClassLoader(),
16 user.getClass().getInterfaces(),this);
17 }
18
19 //proxy:代理类
20 //method:代理类的调用处理程序的方法 的对象
21 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
22 show1();
23 Object invoke = method.invoke(user, args);
24 show2();
25 return invoke;
26 }
27
28 public void show1(){
29 System.out.println("show方法1");
30 }
31
32 public void show2(){
33 System.out.println("show方法2");
34 }
35 }
【注意InvocationHandler导包】
4,测试
1 public class Test {
2 public static void main(String[] args) {
3
4 UserImpl userImpl = new UserImpl();
5
6 InvocationHandlerProxy ihp = new InvocationHandlerProxy();
7 ihp.setUser(userImpl);
8
9 User proxy = (User) ihp.getProxy();
10
11 proxy.add();
12 }
13 }
5,运行结果
四,总结
动态代理的好处
- 可以使真实角色更加纯粹,不用去关注一些公共的事情
- 公共的业务由代理来完成,实现业务的分工
- 公共业务的要扩展的话,可以更加集中和方便
- 一个动态代理,一般代理一类的业务,一个动态代理可以代理多个类,代理接口