模仿JDK动态代理的简单实践
来源:互联网 发布:淘宝上有名的女装店 编辑:程序博客网 时间:2024/05/16 19:00
最近在学习Spring以及MyBatis方面的知识,这些框架里面都会涉及到一个知识点,就是动态代理,所以作者就在慕课网上过了一遍代理模式的知识点,并对视频上的代码进行了简单的分析,加深自己对动态代理的认识。
1.首先是创建一个需要被代理的类:
import java.util.Random;/** * 需要被代理的类 * */public class Car implements Moveable {@Overridepublic void move() {// 实现接口方法try {Thread.sleep(new Random().nextInt(1000));System.out.println("汽车行驶中....");} catch (InterruptedException e) {e.printStackTrace();}}}
2.该类实现了Moveable接口:
/** * 被代理类所实现的接口 * */public interface Moveable {void move();}
3.接着创建一个代理实例的调用处理程序的实现类,用于加强被代理对象。
import java.lang.reflect.Method;/** * 代理实例的调用处理程序的实现类,加强被代理对象 * */public class TimeHandler implements InvocationHandler {//被代理的对象private Object target;//构造方法接收被代理对象public TimeHandler(Object target) {super();this.target = target;}/** * 实现接口方法 */@Overridepublic void invoke(Object proxy, Method m) {try {long starttime = System.currentTimeMillis();System.out.println("汽车开始行驶....");m.invoke(target);long endtime = System.currentTimeMillis();System.out.println("汽车结束行驶.... 汽车行驶时间:"+ (endtime - starttime) + "毫秒!");} catch (Exception e) {e.printStackTrace();}}}
4.该调用实现类实现了 InvocationHandler 接口:
import java.lang.reflect.Method;/** * 代理实例的调用处理程序实现的接口。 * 每个代理实例都具有一个关联的调用处理程序。 * 对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法。 */public interface InvocationHandler {/** * 在代理实例上处理方法。在与方法关联的代理实例上调用方法时,将在调用处理程序上调用此方法。 * @param proxy 在其上调用方法的代理实例。 * @param method 对应于在代理实例上调用的接口方法的 Method 实例。 * Method 对象的声明类将是在其中声明方法的接口,该接口可以是代理类赖以继承方法的代理接口的超接口。 */public void invoke(Object proxy,Method method);}
5.然后创建一个代理类,该类的newProxyInstance会方法一个代理实例:
import java.io.File;import java.lang.reflect.Constructor;import java.lang.reflect.Method;import javax.tools.JavaCompiler;import javax.tools.StandardJavaFileManager;import javax.tools.ToolProvider;import javax.tools.JavaCompiler.CompilationTask;import org.apache.commons.io.FileUtils;/** * 动态代理类 * */public class Proxy {/** * 返回代理类的一个实例,返回的代理类可以被当做被代理类使用(可使用被代理类在接口中声明过的方法) * * @param infce * 被代理类所实现接口的类类型 * @param h * 代理实例的调用处理程序实现的接口。 * @return 代理类的一个实例 * @throws Exception */public static Object newProxyInstance(Class infce, InvocationHandler h) throws Exception {// 换行符String rt = "\r\n";// 方法String methodStr = "";for (Method m : infce.getMethods()) {methodStr +=// 注解"@Override" + rt +// 方法名"public void " + m.getName() + "() {" + rt +// try语句" try{" + rt +// 获取接口中的方法" Method md = " + infce.getName() + ".class.getMethod(\"" + m.getName() + "\");" + rt +// 执行invoke方法" h.invoke(this,md);" + rt +// catch语句块" }catch(Exception e){ e.printStackTrace();}" + rt + "}";}String str = "import java.lang.reflect.Method;" + rt + "public class $Proxy0 implements " + infce.getName()+ " {" + rt + "public $Proxy0(InvocationHandler h) {" + rt + "this.h = h;" + rt + "}" + rt+ " private InvocationHandler h;" + rt + methodStr + rt + "}";// 产生代理类的java文件String filename = System.getProperty("user.dir") + "/bin/$Proxy0.java";File file = new File(filename);FileUtils.writeStringToFile(file, str);// 编译// 拿到编译器JavaCompiler complier = ToolProvider.getSystemJavaCompiler();// 文件管理者StandardJavaFileManager fileMgr = complier.getStandardFileManager(null, null, null);// 获取文件Iterable units = fileMgr.getJavaFileObjects(filename);// 编译任务CompilationTask t = complier.getTask(null, fileMgr, null, null, null, units);// 进行编译t.call();fileMgr.close();// load 到内存ClassLoader cl = ClassLoader.getSystemClassLoader();Class c = cl.loadClass("$Proxy0");Constructor ctr = c.getConstructor(InvocationHandler.class);return ctr.newInstance(h);}}
6.最后调用测试方法测试:
public class Client {/** * 测试方法 * * @throws Exception */public static void main(String[] args) throws Exception {// 创建需要代理的对象。Car car = new Car();// 创建一个代理实例的调用处理对象。InvocationHandler h = new TimeHandler(car);// 调用代理类的静态方法,生成代理实例。Moveable m = (Moveable) Proxy.newProxyInstance(Moveable.class, h);m.move();}}
所得结果如下:
汽车开始行驶....
汽车行驶中....
汽车结束行驶.... 汽车行驶时间:921毫秒!
汽车行驶中....
汽车结束行驶.... 汽车行驶时间:921毫秒!
最后附上项目源码下载地址!!!
点击打开链接
0 0
- 模仿JDK动态代理的简单实践
- JDK动态代理的实践
- 模仿JDK实现动态代理
- 简单的 JDK实现动态代理
- JDK 动态代理的简单理解
- JDK 动态代理的简单理解
- 简单的Jdk动态代理实现:
- java的jdk动态代理简单封装
- jdk动态代理如此简单
- jdk 动态代理简单应用
- Jdk动态代理简单实现
- JDK的动态代理
- JDK的动态代理
- JDK的动态代理
- JDK的动态代理
- JDK的动态代理
- Jdk的动态代理
- JDK和CGLIB动态代理实践
- MPEG2-TS音视频同步原理
- mac终端命令大全介绍
- 关于软件测试的一些基本知识
- docker容器运行后退出,怎么才能一直运行?
- redis主从配置及主从切换
- 模仿JDK动态代理的简单实践
- 内置属性,包与模块
- 【Visual Studio】VS自定义工具栏
- leetcode--3--最长不重复字符串
- LaTeX实战经验:数学公式环境注意事项
- 61.Search for a Range-搜索区间(中等题)
- linux rculist代码分析
- nginx对比haproxy 的反向代理
- 【原】东方耀REACT-NATIVE学习43,ios日期组件 ActionSheetIOS