代理模式(静态代理、JDK 动态代理、CGLIB 动态代理)
- 一、代理模式概述
- 1. 生活中的代理案例
- 2. 为什么要使用代理
- 3. 代理模式在 Java 中的应用
- 4. 概述
- 5. 生活中代理图示
- 二、代理的实现方式
- 1. Java 中代理图示
- 2. 静态代理
- 2.1 案例
- 2.2 实现案例
- 2.3 静态代理存在的问题
- 三、动态代理
- 1. 概述
- 2. JDK 动态代理
- 2.1 基础准备
- 2.2 实现 InvocationHandler 接口
- 2.3 测试
- 2.4 底层运行原理
- 3. CGLIB 动态代理
- 3.1 基础准备
- 3.2 实现方法拦截 MethodInterceptor
- 3.3 测试
- 3.4 底层运行原理
- 四、总结
一、代理模式概述
1. 生活中的代理案例
- 房屋中介代理:客户手里没有房源信息,找一个中介
- 商品代购:这些代购者可以去哪到比较低成本的商品,拥有自己的渠道
2. 为什么要使用代理
对于消费者而言,可以减少成本,只需要关心自己需要的商品,不需要去寻找渠道或者是找房源。
3. 代理模式在 Java 中的应用
- 统一异常处理
- MyBatis 使用了代理
- Spring Aop 实现原理
- 日志框架
4. 概述
- 代理模式(Proxy Pattern):是 23 中设计模式中的一种,属于结构型的模式。指一个对象本身不做实际的操作,而是通过其他对象来得到自己想要得到的结果。
- 意义: 目标对象只需要关心自己的实现细节,通过代理对象来实现功能的增强,可以扩展目标对象的功能。
- 体现了非常重要的编程思想:不能随便修改源码,通过修改代理的方式来实现功能的扩展。
5. 生活中代理图示
二、代理的实现方式
1. Java 中代理图示
- 元素组成
- 接口,定义行为和规范的
- 被代理类,是目标对象
- 代理类,做功能增强的
2. 静态代理
2.1 案例
通过代理模式实现事务操作
2.2 实现案例
- 创建 domain 对象
@Data
public class Student {private String name;private int age;}
- 创建 service 接口定义规范
public interface IStudentService {/*** 添加学生*/void save();/*** 查询学生信息* @param id* @return*/Student query(Long id);}
- 创建实现类,被代理类
public class IStudentServiceImpl implements IStudentService {public void save() {System.out.println("保存学生信息");}public Student query(Long id) {Student student = new Student();student.setName("sy");student.setAge(18);return student;}
}
- 创建事务类对象
public class DaoTransaction {public void before() {System.out.println("开始事务操作");}public void after() {System.out.println("关闭事务");}}
- 创建代理类对象
public class ProxyStudent implements IStudentService {// 目标类对象private IStudentServiceImpl iStudentService;// 需要做的增强对象private DaoTransaction daoTransaction;// 通过构造器获取目标类和增强类对象public ProxyStudent(IStudentServiceImpl iStudentService, DaoTransaction daoTransaction) {this.iStudentService = iStudentService;this.daoTransaction = daoTransaction;}public void save() {// 开始事务操作daoTransaction.before();// 目标类操作iStudentService.save();// 关闭事务操作daoTransaction.after();}public Student query(Long id) {return iStudentService.query(id);}
}
- 测试代理类对象
public class TestStudent {@Testpublic void