自定义实现Java动态代理
转自:https://www.cnblogs.com/rjzheng/p/8750265.html
一 借助JDK的API实现:
1.先创建一个接口,并实现它
public interface Person {
void eat();
}
public class PersonImpl implements Person {
@Override
public void eat() {
System.out.println("eat............");
}
}
2.实现InvocationHandler:每一个动态代理类都要实现这个接口
public class PersonInvocationHandler implements InvocationHandler {
//我们要代理的真实对象
private Object obj;
public PersonInvocationHandler(Object obj) {
this.obj = obj;
}
/**
* Object proxy:
* 1. 可以使用反射获取代理对象的信息(也就是proxy.getClass().getName())。
* 2. 可以将代理对象返回以进行连续调用,这就是proxy存在的目的,因为this并不是代理对象。
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before eat.......");
//当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
method.invoke(obj, args);
System.out.println("after eat.......");
return null;
}
}
3.测试
public class JdkTest {
public static void main(String[] args) {
PersonInvocationHandler personInvocationHandler = new PersonInvocationHandler(new PersonImpl());
Person personProxy = (Person) Proxy.newProxyInstance(PersonImpl.class.getClassLoader(),
PersonImpl.class.getInterfaces(), personInvocationHandler);
personProxy.eat();
}
}
返回结果:

二 自定义动态代理
1.自定义InvocationHandler
public interface MyInvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}
2.实现自定义的MyInvocationHandler
public class PersonInvocationHandler implements MyInvocationHandler {
//我们要代理的真实对象
private Object obj;
public PersonInvocationHandler(Object obj) {
this.obj = obj;
}
/**
* Object proxy:
* 1. 可以使用反射获取代理对象的信息(也就是proxy.getClass().getName())。
* 2. 可以将代理对象返回以进行连续调用,这就是proxy存在的目的,因为this并不是代理对象。
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before eat.......");
//当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
method.invoke(obj, args);
System.out.println("after eat.......");
return null;
}
}
3.自定义ClassLoader
public class MyClassLoader extends ClassLoader{
private File classPathFile;
public MyClassLoader() {
String classPath = MyClassLoader.class.getResource("").getPath();
this.classPathFile = new File(classPath);
}
public Class<?> findClass(String name) {
String className = MyClassLoader.class.getPackage().getName() + "." + name;
if (classPathFile != null){
File file = new File(classPathFile, name + ".class");
FileInputStream inputStream = null;
ByteArrayOutputStream outputStream = null;
try {
inputStream = new FileInputStream(file);
outputStream = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int len ;
while ((len = inputStream.read(buf)) != -1){
outputStream.write(buf, 0, len);
}
return defineClass(className, outputStream.toByteArray(), 0, outputStream.size());
}catch (Exception e){
e.printStackTrace();
}finally {
if(null!=inputStream){
try {
inputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(null!=outputStream){
try {
outputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
return null;
}
}
4.自定义Proxy代理类
主要流程:1.将源码输入到Java文件
2.将Java文件编译成class文件
3.将class加载进jvm
4.返回代理类对象
public class MyProxy {
public static final String ln = "\r\n";
public static Object newProxyInstance(MyClassLoader classLoader,
Class<?>[] interfaces, MyInvocationHandler handler) {
try {
//1.java源码
String src = generateSrc(interfaces);
//2.将源码输出到Java文件中
String filePath = MyProxy.class.getResource("").getPath();
System.out.println(filePath);
File file = new File(filePath + "$Proxy0.java");
FileWriter fw = new FileWriter(file);
fw.write(src);
fw.flush();
fw.close();
//3.将Java文件编译成class文件
JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager manager = javaCompiler.getStandardFileManager(null, null, null);
Iterable iterable = manager.getJavaFileObjects(file);
JavaCompiler.CompilationTask task = javaCompiler.getTask(null, manager, null, null,null, iterable);
task.call();
manager.close();
//4.将class加载进jvm
Class proxyClass = classLoader.findClass("$Proxy0");
file.delete();
//5.返回代理类对象
Constructor constructor = proxyClass.getConstructor(MyInvocationHandler.class);
return constructor.newInstance(handler);
}catch (Exception e){
e.printStackTrace();
}
return null;
}
//Java源码
private static String generateSrc(Class<?>[] interfaces) {
// TODO Auto-generated method stub
StringBuffer sb = new StringBuffer();
sb.append("package xin.hangzhi.jdk.proxy.demo.custom;" + ln);
sb.append("import java.lang.reflect.Method;" + ln);
sb.append("public class $Proxy0 implements " + interfaces[0].getName() + "{" + ln);
sb.append("private MyInvocationHandler h;"+ln);
sb.append("public $Proxy0(MyInvocationHandler h) { " + ln);
sb.append("this.h = h;"+ln);
sb.append("}" + ln);
for (Method m : interfaces[0].getMethods()) {
sb.append("public " + m.getReturnType().getName() + " "
+ m.getName() + "() {" + ln);
sb.append("try{" + ln);
sb.append("Method m = " + interfaces[0].getName()
+ ".class.getMethod(\"" + m.getName()
+ "\",new Class[]{});" + ln);
sb.append("this.h.invoke(this,m,null);" + ln);
sb.append("}catch(Throwable e){" + ln);
sb.append("e.printStackTrace();" + ln);
sb.append("}"+ln);
sb.append("}"+ln);
}
sb.append("}" + ln);
return sb.toString();
}
}
5.测试结果

自定义实现Java动态代理的更多相关文章
- JAVA动态代理模式(从现实生活角度理解代码原理)
所谓动态代理,即通过代理类:Proxy的代理,接口和实现类之间可以不直接发生联系,而可以在运行期(Runtime)实现动态关联. java动态代理主要是使用java.lang.reflect包中的两个 ...
- Java 动态代理
被代理的接口特点: 1. 不能有重复的接口,以避免动态代理类代码生成时的编译错误. 2. 这些接口对于类装载器必须可见,否则类装载器将无法链接它们,将会导致类定义失败. 3. 需被代理的所有非 pub ...
- 如何实现在已有代码之后添加逻辑之java动态代理
在上篇博客中讨论到java的静态代理, 就是通过组合的方法,前提是委托类需要实现一个接口,代理类也实现这个这个 接口,从何组合两个类,让代理类给委托类添加功能! 知道java的静态代理,我们又遇到一个 ...
- Java 动态代理机制分析及扩展
Java 动态代理机制分析及扩展,第 1 部分 王 忠平, 软件工程师, IBM 何 平, 软件工程师, IBM 简介: 本文通过分析 Java 动态代理的机制和特点,解读动态代理类的源代码,并且模拟 ...
- [转]Java 动态代理机制分析及扩展
引言 Java 动态代理机制的出现,使得 Java 开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类.代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执 ...
- JAVA动态代理详解
1.什么是代理 代理模式是常用的Java 设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等. 2.什么是动态代理 在程 ...
- Java动态代理深入解析
要想了解Java动态代理,首先要了解什么叫做代理,熟悉设计模式的朋友一定知道在Gof总结的23种设计模式中,有一种叫做代理(Proxy)的对象结构型模式,动态代理中的代理,指的就是这种设计模式. 在我 ...
- 深入浅出Java动态代理
文章首发于[博客园-陈树义],点击跳转到原文深入浅出Java动态代理 代理模式是设计模式中非常重要的一种类型,而设计模式又是编程中非常重要的知识点,特别是在业务系统的重构中,更是有举足轻重的地位.代理 ...
- JAVA 动态代理原理和实现
在 Java 中动态代理和代理都很常见,几乎是所有主流框架都用到过的知识.在面试中也是经常被提到的话题,于是便总结了本文. Java动态代理的基本原理为:被代理对象需要实现某个接口(这是前提),代理对 ...
随机推荐
- java中内部类
package com.xt.instanceoftest; import com.xt.instanceoftest.Body.Heart; public class StaticInnerClas ...
- ARC 100 C - Linear Approximation题解---三分法
题目链接: https://arc100.contest.atcoder.jp/tasks/arc100_a 分析: 比赛时做这题想到一个瞎搞的方法就是在平均数上下波动一下取最小值,然后大佬yjw学长 ...
- scala新版本学习(3)
1.REPL:读取->求值->打印->循环.Scala程序将输入的内容快速的编译成为字节码,然后字节码文件交给Java虚拟机进行执行. 2.val是值不可变,var值可变.在变量声明 ...
- PHP高级进阶之路
一:常见模式与框架 学习PHP技术体系,设计模式,流行的框架 常见的设计模式,编码必备 Laravel.ThinkPHP开发必不可少的最新框架 YII.Symfony4.1核心源码剖析 二:微服务架构 ...
- 防范DDoS攻击的15个方法
0x01 背景 为了对抗 DDoS(分布式拒绝服务)攻击,你需要对攻击时发生了什么有一个清楚的理解..简单来讲,DDoS 攻击可以通过利用服务器上的漏洞,或者消耗服务器上的资源(例如 内存.硬盘等等) ...
- 架构师成长之路5.7-Saltstack数据系统
点击架构师成长之路 架构师成长之路5.7-Saltstack数据系统 1. Saltstack的两种数据系统 Grains Pollars 2. Saltstack数据系统---Grains Grai ...
- BZOJ1079 [SCOI2008]着色方案[组合计数DP]
$有a_{1}个1,a_{2}个2,...,a_{n}个n(n<=15,a_{n}<=5),求排成一列相邻位不相同的方案数.$ 关于这题的教训记录: 学会对于复杂的影响分开计,善于发现整体 ...
- 本地安装sass出错问题解析
2016年3月23日个人博客文章--迁移到segmentfault 安装sass ruby安装因为sass依赖于ruby环境,所以装sass之前先确认装了ruby.先导官网下载个ruby 在安装的时候 ...
- .NET Compiler Platform,一个.NET编译平台
.NET Compiler Platform,一个.NET编译平台 如何利用C# Roslyn编译器写一个简单的代码提示/错误检查? OK, 废话不多说,这些天在写C#代码时突然对于IDE提示有了 ...
- 命令方式 搭建 (简易)Maven项目
原料:1.配好的Maven环境变量 2.c m d命令 win + r 输入 cmd 切换到此项目所要存在的位置 使用命令创建文件夹 切换 到 maven_demo中 输入 cd mave ...