一、代理模式的作用
二、代理模式本质
例子:
<input type="button" onclick="处理函数">
三、生活案例
案例:饭前便后要洗手
分析:
1.分析出主要业务和次要业务
【主要业务】:吃饭,上厕所
【次要业务】:洗手
2.JDK代理模式实现
2.1、接口角色:定义所有需要被监听行为
BaseService.java
- 1 package com.chenyanbin.service;
- 2
- 3 /*
- 4 * 只有需要被监控的行为才有资格在这里声明
- 5 */
- 6 public interface BaseService {
- 7 public void Eat();
- 8 public void Wc();
- 9 }
2.2、接口实现类:中国人、印度人
Person.java
- 1 package com.chenyanbin.serviceImpl;
- 2
- 3 import com.chenyanbin.service.BaseService;
- 4
- 5 public class Person implements BaseService {
- 6
- 7 @Override
- 8 public void Eat() { //主要业务,代理模式要求开发任务只关心主要业务
- 9 System.out.println("使用筷子吃饭");
- 10 }
- 11
- 12 @Override
- 13 public void Wc() {
- 14 System.out.println("测试地球重力是否存在");
- 15 }
- 16 }
2.3、通知类:1)次要业务进行具体实现 2)通知JVM,当前被拦截的主要业务方法与次要业务方法应该如何绑定执行
Invaction.java
- 1 package com.chenyanbin.util;
- 2
- 3 import java.lang.reflect.InvocationHandler;
- 4 import java.lang.reflect.Method;
- 5
- 6 import com.chenyanbin.service.BaseService;
- 7
- 8 public class Invaction implements InvocationHandler {
- 9 private BaseService obj;// 具体被监控对象
- 10
- 11 public Invaction(BaseService param) {
- 12 this.obj = param;
- 13 }
- 14
- 15 /*
- 16 * invoke方法:被监控行为将要执行时,会被JVM拦截,被监控行为和行为实现方会被作为参数输送到invoke
- 17 * ***通知JVM,这个被拦截方法是如何与当前次要业务方法绑定实现 invoke方法三个参数 小明.Eat();//JVM拦截
- 18 * Eat方法封装为Method类型方法 Eat方法运行时所有的实参封装到Object[] 将负责监控小明的代理对象作为invoke方法第一个参数
- 19 *
- 20 */
- 21 @Override
- 22 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- 23 // 0.局部变量,接受主要业务方法执行完毕后返回值
- 24 Object value;
- 25 // 1.确认当前被拦截行为
- 26 String methodName = method.getName();
- 27 // 2.根据被拦截行为不同,决定主要业务和次要业务如何绑定执行
- 28 if ("Eat".equals(methodName)) { // 饭前要洗手
- 29 Wash();// 洗手
- 30 value = method.invoke(this.obj, args);// 当前主要业务
- 31 } else { // 便后洗手
- 32 value = method.invoke(this.obj, args);// 当前主要业务
- 33 Wash();// 洗手
- 34 }
- 35 return value; //返回被拦截方法
- 36 }
- 37
- 38 // 次要业务
- 39 public void Wash() {
- 40 System.out.println("--------洗手--------");
- 41 }
- 42 }
2.4、监控对象(代理对象):1)被监控实例对象 2)需要被监控行为 3)具体通知类实例对象
ProxyFactory.java
- 1 package com.chenyanbin.util;
- 2
- 3 import java.lang.reflect.InvocationHandler;
- 4 import java.lang.reflect.Proxy;
- 5
- 6 import com.chenyanbin.service.BaseService;
- 7
- 8 public class ProxyFactory {
- 9 /*
- 10 * JDK动态代理模式下,代理对象的数据类型 应该由监控行为来描述 参数:Class文件,监控类
- 11 */
- 12 public static BaseService build(Class classFile) throws Exception {
- 13 //1.创建被监控实例对象
- 14 BaseService obj = (BaseService) classFile.getDeclaredConstructor().newInstance();
- 15 //2.创建通知对象
- 16 InvocationHandler adviser=new Invaction(obj);
- 17 //3.向JVM申请负责监控obj对象指定行为的监控对象(代理对象)
- 18 /*
- 19 * loader:被监控对象隶属的类文件在内存中真实地址
- 20 * interfaces:被监控对象隶属的类文件实现接口
- 21 * h:监控对象发现小明要执行被监控行为,应该由哪一个通知对象进行辅助
- 22 */
- 23 BaseService $proxy=(BaseService)Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), adviser);
- 24 return $proxy;
- 25 }
- 26 }
测试类
TestMain.java
- 1 import com.chenyanbin.service.BaseService;
- 2 import com.chenyanbin.serviceImpl.Person;
- 3 import com.chenyanbin.util.ProxyFactory;
- 4
- 5 public class TestMain {
- 6
- 7 public static void main(String[] args) throws Exception {
- 8 //mike.Eat();
- 9 // Person mike=new Person();
- 10 BaseService mike = ProxyFactory.build(Person.class);
- 11 mike.Eat();
- 12 }
- 13 }
吃饭

上厕所

项目目录结构
