设计模式之动态代理
一、代理的简要介绍
2、代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
3、作用:增强一个类中的某个方法.对程序进行扩展,Spring框架中AOP。
二、
- 动态代理它可以直接给某一个目标(被代理 对象)对象(实现了某个或者某些接口)生成一个代理对象,而不需要代理类存在,如上图中经理人需要存在。
- 动态代理与代理模式原理是一样的,只是它没有具体的代理类,直接通过反射生成了一个代理对象
2、动态代理的分类
- spring中动态代理:cglib 继承
3、动态代理作用
- 最终是学习AOP(面向切面编程),它与装饰者模式有点相似,它比装饰者模式还要灵活!
三、
-
Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)生成一个代理对象
-
参数1:ClassLoader loader 代理对象的类加载器 一般使用被代理对象的类加载器
-
参数2:Class<?>[] interfaces 代理对象的要实现的接口 一般使用的被代理对象实现的接口
-
参数3:InvocationHandler h (接口)执行处理类
-
-
InvocationHandler中的invoke(Object proxy, Method method, Object[] args)方法:调用代理类的任何方法,此方法都会执行
-
参数3.1:代理对象(慎用)
-
参数3.2:当前执行的方法
-
参数3.3:当前执行的方法运行时传递过来的参数
-
返回值:当前方法执行的返回值
-
-
2、Proxy.newProxyInstance方法参数介绍
- ClassLoader:类加载器!
- 它是用来加载器的,把.class文件加载到内存,形成Class对象!
- Class[] interfaces:指定要实现的接口们
- InvocationHandler:代理对象的所有方法(个别不执行,getClass())都会调用InvocationHandler的invoke()方法。
3、InvocationHandler方法参数介绍
public Object invoke(Object proxy, Method method, Object[] args);
这个invoke()方法在什么时候被调用!在调用代理对象所实现接口中的方法时
- Object proxy:当前对象,即代理对象!在调用谁的方法!
- Method method:当前被调用的方法(目标方法)
- Object[] args:实参!
4、简单示例
1 import org.junit.Test; 2 import java.lang.reflect.InvocationHandler; 3 import java.lang.reflect.Method; 4 import java.lang.reflect.Proxy; 5 6 public class ProxyDemo { 7 @Test 8 public void test(){ 9 Person woman = new Woman(); 10 Person person =(Person) Proxy.newProxyInstance(woman.getClass().getClassLoader(), 11 woman.getClass().getInterfaces(), 12 new InvocationHandler() { 13 @Override 14 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 15 //增强sleep方法 16 if ("sleep".equals(method.getName())) { 17 System.out.println("大字睡姿....."); 18 return null; 19 } 20 return method.invoke(woman, args); 21 } 22 }); 23 person.eat(); 24 person.sleep(); 25 String s = person.run("快步跑"); 26 System.out.println(s); 27 } 28 29 interface Person{ 30 void eat(); 31 void sleep(); 32 String run(String state); 33 } 34 35 class Woman implements Person{ 36 37 @Override 38 public void eat() { 39 System.out.println("小口吃..."); 40 } 41 42 @Override 43 public void sleep() { 44 System.out.println("淑女睡..."); 45 } 46 47 @Override 48 public String run(String state) { 49 return "Woman" + state + "......"; 50 } 51 } 52 }
四、动态代理模型
- 目标对象:被增强的对象
- 代理对象:需要目标对象,然后在目标对象上添加了增强后的对象!
- 目标方法:增强的内容
- 代理对象 = 目标对象 + 增强
五、案例
案例1:Waiter
1 package demo2;
2
3 import org.junit.Test;
4 import java.lang.reflect.InvocationHandler;
5 import java.lang.reflect.Method;
6 import java.lang.reflect.Proxy;
7
8 public class Demo2 {
9 @Test
10 public void fun1() {
11 Waiter manWaiter = new ManWaiter();
12 /*
13 * 给出三个参数,来创建方法,得到代理对象
14 * */
15 ClassLoader loader = this.getClass().getClassLoader();
16 Class[] interfaces = {Waiter.class};
17 InvocationHandler h = new WaiterInvocationHandler(manWaiter);//参数manWaiter类表示目标对象
18 //得到代理对象,代理对象就是在目标对象的基础上进行了增强的对象!
19 Waiter waiterProxy = (Waiter) Proxy.newProxyInstance(loader,interfaces,h);
20 waiterProxy.serve();//前面添加"你好",后面添加"再见"
21
22 }
23 }
24 class WaiterInvocationHandler implements InvocationHandler {
25 private Waiter waiter;//目标对象
26
27 public WaiterInvocationHandler(Waiter waiter) {
28 this.waiter = waiter;
29 }
30 @Override
31 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
32 System.out.println("您好!");
33 this.waiter.serve();//调用目标对象的目标方法
34 System.out.println("再见!");
35 return null;
36 }
37 }
1 package demo2;
2
3 public class ManWaiter implements Waiter {
4 @Override
5 public void serve() {
6 System.out.println("服务中...");
7 }
8 }
1 package demo2;
2
3 //服务
4 public interface Waiter {
5 //服务
6 public void serve();
7 }
案例2:
1 /**
2 * 目标是让目标对象和增强都可以切换!
3 */
4 public class Demo3 {
5 @Test
6 public void fun1() {
7 ProxyFactory factory = new ProxyFactory();
8 factory.setTargetObject(new ManWaiter());
9 factory.setBeforeAdvice(new BeforeAdvice() { //设置前置增强
10 @Override
11 public void before() {
12 System.out.println("您好!");
13 }
14 });
15 factory.setAfterAdvice(new AfterAdvice() { //设置后置增强
16 @Override
17 public void after() {
18 System.out.println("再见!");
19 }
20 });
21
22 Waiter waiter = (Waiter) factory.createProxy();
23 waiter.serve();
24 }
25 }
1 package demo3;
2
3 import java.lang.reflect.InvocationHandler;
4 import java.lang.reflect.Method;
5 import java.lang.reflect.Proxy;
6
7 /**
8 * 它用来生成代理对象
9 * 它需要所有的参数
10 * 目标对象
11 * 增强
12 */
13 /*
14 * 1、创建代理工厂
15 * 2、给工厂设置三样东西:
16 * 目标对象:setTargetObject(XXX);
17 * 前置增强:setBeforeAdvice(该接口的实现)
18 * 后置增强:setAfterAdvice(该接口的实现)
19 * 3、调用createProxy()得到代理对象
20 * 执行代理对象方法时:
21 * 执行BeforeAdvice的before()
22 * 目标对象的目标方法
23 * 执行AfterAdvice的after()
24 * */
25 public class ProxyFactory {
26 private Object targetObject;//目标对象
27 private BeforeAdvice beforeAdvice;//前置增强
28 private AfterAdvice afterAdvice;//后置增强
29
30 //用来生成代理对象
31 public Object createProxy() {
32 /*
33 * 1、给出三大参数
34 * */
35 ClassLoader loader = this.getClass().getClassLoader();
36 Class[] interfaces = targetObject.getClass().getInterfaces();
37 InvocationHandler h = new InvocationHandler() {
38 @Override
39 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
40 /*
41 * 在调用代理对象的方法时会执行这里的内容
42 * */
43 //执行前置增强
44 if (beforeAdvice != null) {
45 beforeAdvice.before();
46 }
47 Object result = method.invoke(targetObject,args);//执行目标对象的目标方法
48 //执行后置增强
49 if (afterAdvice != null) {
50 afterAdvice.after();
51 }
52 return result;
53 }
54 };
55 //2、得到代理对象
56 Object proxObject = Proxy.newProxyInstance(loader,interfaces,h);
57 return proxObject;
58 }
59 public Object getTargetObject() {
60 return targetObject;
61 }
62 public void setTargetObject(Object targetObject) {
63 this.targetObject = targetObject;
64 }
65 public BeforeAdvice getBeforeAdvice() {
66 return beforeAdvice;
67 }
68 public void setBeforeAdvice(BeforeAdvice beforeAdvice) {
69 this.beforeAdvice = beforeAdvice;
70 }
71 public AfterAdvice getAfterAdvice() {
72 return afterAdvice;
73 }
74 public void setAfterAdvice(AfterAdvice afterAdvice) {
75 this.afterAdvice = afterAdvice;
76 }
77 }
1 /**
2 * 前置增强
3 */
4 public interface BeforeAdvice {
5 public void before();
6 }
1 /**
2 * 后置增强
3 */
4 public interface AfterAdvice {
5 public void after();
6 }
案例2类图: