一:什么是动态代理:
利用反射机制在运行时创建代理类。接口、被代理类不变。
二:动态代理和静态代理的不同:
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 }
注:抽象角色、真实角色 的实际代码此处省略(与静态代理实现步骤一样)
【我们可根据不同的业务需求,套用万能动态代理模板即可】