代理模式(静态代理、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 {
@Test
public void