没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
Java 动态代理详解
动态代理在 Java 中有着广泛的应用,比如 Spring AOP、Hibernate 数据查询、测
试框架的后端 mock、RPC 远程调用、Java 注解对象获取、日志、用户鉴权、全
局性异常处理、性能监控,甚至事务处理等。
本文主要介绍 Java 中两种常见的动态代理方式:JDK 原生动态代理和 CGLIB 动态
代理。
代理模式
本文将介绍的 Java 动态代理与设计模式中的代理模式有关,什么是代理模式呢?
代理模式:给某一个对象提供一个代理,并由代理对象来控制对真实对象的访问。
代理模式是一种结构型设计模式。
代理模式角色分为 3 种:
Subject(抽象主题角色):定义代理类和真实主题的公共对外方法,也是代理类
代理真实主题的方法;
RealSubject(真实主题角色):真正实现业务逻辑的类;
Proxy(代理主题角色):用来代理和封装真实主题;
代理模式的结构比较简单,其核心是代理类,为了让客户端能够一致性地对待真
实对象和代理对象,在代理模式中引入了抽象层
代理模式按照职责(使用场景)来分类,至少可以分为以下几类:1、远程代理。
2、虚拟代理。 3、Copy-on-Write 代理。 4、保护(Protect or Access)代理。
5、Cache 代理。 6、防火墙(Firewall)代理。 7、同步化(Synchronization)代
理。 8、智能引用(Smart Reference)代理等等。
如果根据字节码的创建时机来分类,可以分为静态代理和动态代理:
� 所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和真实主题
角色的关系在运行前就确定了。
� 而动态代理的源码是在程序运行期间由 JVM 根据反射等机制动态的生成,所以在运
行前并不存在代理类的字节码文件
静态代理
我们先通过实例来学习静态代理,然后理解静态代理的缺点,再来学习本文的主
角:动态代理
编写一个接口 UserService ,以及该接口的一个实现类 UserServiceImpl
public interface UserService {
public void select();
public void update();
}
public class UserServiceImpl implements UserService {
public void select() {
System.out.println("查询 selectById");
}
public void update() {
System.out.println("更新 update");
}
}
我们将通过静态代理对 UserServiceImpl 进行功能增强,在调用 select 和
update 之前记录一些日志。写一个代理类 UserServiceProxy,代理类需要实现
UserService
public class UserServiceProxy implements UserService {
private UserService target; // 被代理的对象
public UserServiceProxy(UserService target) {
this.target = target;
}
public void select() {
before();
target.select(); // 这里才实际调用真实主题角色的方法
after();
}
public void update() {
before();
target.update(); // 这里才实际调用真实主题角色的方法
after();
}
private void before() { // 在执行方法之前执行
System.out.println(String.format("log start time [%s] ", new Date()));
}
private void after() { // 在执行方法之后执行
System.out.println(String.format("log end time [%s] ", new Date()));
}
}
客户端测试
public class Client1 {
public static void main(String[] args) {
UserService userServiceImpl = new UserServiceImpl();
UserService proxy = new UserServiceProxy(userServiceImpl);
proxy.select();
proxy.update();
}
}
输出
log start time [Thu Dec 20 14:13:25 CST 2018]
查询 selectById
log end time [Thu Dec 20 14:13:25 CST 2018]
log start time [Thu Dec 20 14:13:25 CST 2018]
更新 update
log end time [Thu Dec 20 14:13:25 CST 2018]
通过静态代理,我们达到了功能增强的目的,而且没有侵入原代码,这是静态代
理的一个优点。
静态代理的缺点
虽然静态代理实现简单,且不侵入原代码,但是,当场景稍微复杂一些的时候,
静态代理的缺点也会暴露出来。
1、 当需要代理多个类的时候,由于代理对象要实现与目标对象一致的接口,有
两种方式:
� 只维护一个代理类,由这个代理类实现多个接口,但是这样就导致代理类过于庞大
� 新建多个代理类,每个目标对象对应一个代理类,但是这样会产生过多的代理类
2、 当接口需要增加、删除、修改方法的时候,目标对象与代理类都要同时修改,
不易维护。
如何改进?
当然是让代理类动态的生成啦,也就是动态代理。
为什么类可以动态的生成?
这就涉及到 Java 虚拟机的类加载机制了,推荐翻看《深入理解 Java 虚拟机》7.3
节 类加载的过程。
Java 虚拟机类加载过程主要分为五个阶段:加载、验证、准备、解析、初始化。
其中加载阶段需要完成以下 3 件事情:
1. 通过一个类的全限定名来获取定义此类的二进制字节流
剩余27页未读,继续阅读
资源评论
Andy&lin
- 粉丝: 97
- 资源: 214
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功