Java核心技术之动态代理
时间:2022-07-22
本文章向大家介绍Java核心技术之动态代理,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
提出一个问题
在实际的编程过程中,你可能会遇到这样的问题。你拥有以下的业务逻辑:A, B 和 C,在最初的设计过程中,你的程序在执行B之前,要先执行A,在执行B之后,要紧接着最后执行C。可是随着业务的调整,你不想在B之前执行A了,甚至想重新增加一个D来替换A。有没有不修改代码的前提下动态的进行这样的逻辑调整?动态代理就可以用来解决这个问题。
什么是动态代理
Java标准库提供了一种动态代理(Dynamic Proxy)的机制:可以在运行期动态创建某个interface
的实例。
使用动态代理,一般是为了给需要实现的方法添加预处理或者添加后续操作,但是不干预实现类的正常业务,把一些基本业务和主要的业务逻辑分离。
23种设计模式中的面向切面编程 (AOP) 就是以动态代理机制基础的。
基于JDK的动态代理如何实现
首先定义一个接口
package ProxyStudy;
public interface Hello {
public void sayHello();
}
然后编写这个接口的实现类
package ProxyStudy;
public class Helloer implements Hello {
@Override
public void sayHello() {
System.out.println("Helloer says: Hello!");
}
}
在静态实现的过程中,你一定会这样做
Helloer helloer = new Helloer();
helloer.sayHello();
但是在动态代理中,首先要定义一个 ProxyHandler 类,并实现 InvocationHandler 接口。
package ProxyStudy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class ProxyHandler implements InvocationHandler {
private Object subject;
public ProxyHandler(Object subject) {
this.subject = subject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("I am ready to do something...");
Object invoker = method.invoke(subject, args);
System.out.println("I am done~");
return invoker;
}
}
这样,你就可以通过Proxy来动态生成一个代理对象,然后通过调用这个代理对象来实现真正对象的方法。实际上调用的是代理对象的invoke方法。
package ProxyStudy;
import java.lang.reflect.Proxy;
public class Main {
public static void main(String[] args) {
// 创建目标对象
Hello hello = new Helloer();
// 创建调用处理器对象
ProxyHandler proxyHandler = new ProxyHandler(hello);
// 动态生成代理对象
Hello helloProxy = (Hello) Proxy.newProxyInstance(
Helloer.class.getClassLoader(), Helloer.class.getInterfaces(), proxyHandler);
// 通过代理对象调用方法
helloProxy.sayHello();
}
}
实际的输出:
动态代理的意义
如上面的代码,你可以把“I am ready to do something”替换成一些执行真正方法前要进行的东西,把“I am done” 替换成一些执行真正方法后要进行的“收尾”工作的东西。动态代理使得在不修改业务类的情况下,能很方便的增加一些其他操作。
- 调整渐变下降的学习率
- 多线程之传统多线程
- ios 常用的正则表达式(手机号邮箱md5加密验证空字符串等)
- Spring Cloud构建微服务架构:Hystrix监控面板【Dalston版】
- 云原生应用的12要素
- Universal-Image-Loader源码分析,及常用的缓存策略
- ios textView跟随键盘的移动
- Android:屏保软件的开发
- CoordinatorLayout
- 从零开始的Spring Security Oauth2(二)
- 简化Swagger使用的自制Starter:spring-boot-starter-swagger,欢迎使用和吐槽
- demo3同通讯录展示的方式分组排序
- Android手势研究(textview及listview对比验证)
- demo2动态加载显示商品详情页
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 性能分析(1)- Java 进程导致 CPU 使用率升高,问题怎么定位?
- 安全服务之安全基线及加固(三)Apache篇
- 使用docsify来管理文献
- Cypress系列(41)- Cypress 的测试报告
- SSRF绕过
- 性能测试必备知识(6)- 如何查看“CPU 上下文切换”
- flex布局 div盒子居中
- 使用Apple Configurator 2提取商店ipa or app文件
- Spring 自动装配模式之byType
- 使用ATOMac进行Mac自动化测试
- 【赵渝强老师】什么是Oracle的数据字典?
- antd 如何在 src目录下 引入 Public 目录下的文件
- (精编)Python与安全(三)SSTI服务器模板注入
- 一年经验Java开发0713面试
- 【分享】MicroBlaze大内部存储器(AXI BRAM)设计