java之动态代理

mac2024-11-30  43

Java之动态代理

文章目录

Java之动态代理基本说明例子代码接口`LinuxService`实现类`LinuxServiceImpl`想要代理接口的代理对象执行类结果

基本说明

我们的目标是:在不改变目标对象方法的情况下对方法进行增强!

动态代理类的字节码在程序运行时由Java反射机制动态生成,而无需手动编写它的源代码。

简化了编程工作提高了软件系统的可扩展性

Java 反射机制可以生成任意类型的动态代理类。java.lang.reflect 包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力。

例子

目标:现在有一个linux命令的接口LinuxService,接口中有个方法是创建目录的方法mkdir,想在创建目录的时候能指定一个目标路径。但是不改变LinuxService中的方法。方案:使用动态代理,在使用LinuxService接口中的mkdir时,代理对象指定目录,但在调用方看来,使用的就是LinuxService类的实例中的mkdir方法。

代码

接口LinuxService

public interface LinuxService { /** * make directory, 创建目录 */ void mkdir(); /** * 如果文件不存在,则会建立空文件;如果文件已经存在,则会修改文件的时间戳 */ void touch(); /** * 编辑文件 */ void vim(); /** * 连接文件并打印输出到标准输出 查看文件内容 */ void cat(); }

实现类LinuxServiceImpl

public class LinuxServiceImpl implements LinuxService { private static String centreMessage = "我的核心实现是:"; @Override public void mkdir() { System.out.println(centreMessage+"创建一个文件夹!"); } @Override public void touch() { System.out.println(centreMessage+"创建一个用来编辑的文件!"); } @Override public void vim() { System.out.println(centreMessage+"打开上面的文件并编辑!"); } @Override public void cat() { System.out.println(centreMessage+"查看编辑过后的文件!"); } }

想要代理接口的代理对象

public class LinuxServiceProxy implements InvocationHandler { /** * 要代理的核心对象 B是A的代理,则target=A * B = LinuxServiceProxy A = LinuxService */ private Object target; public LinuxServiceProxy(Object target){ this.target = target; } /** * jdk动态代理 * @param proxy 指被代理的对象。 * @param method 要调用的方法 * @param args 方法调用时所需要的参数 * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("=======代理对象开始工作========"); System.out.println("进入/Users/mac/Documents目录下后,创建一个新目录test,之后在/test中创建文件以及编辑文件!"); //执行真正的核心的方法 即执行LinuxService中接口中真正关心的方法。 Object result=method.invoke(target, args); System.out.println("=======执行结束后跟我说一下========"); return result; } }

执行类

public class TestLinuxProxy { public static void main(String[] args) { /** * 有一个linux方法的接口,它定义了要实现这些方法的规范,LinuxServiceImpl是接口的具体实现。 * 我要用它方法的具体实现,但我想先指定一个目录。 */ LinuxService linuxService = new LinuxServiceImpl(); /** * 想指定一个目录,但是LinuxService并没有提供指定目录的功能 * 我去找它的代理。 */ LinuxServiceProxy linuxServiceProxy = new LinuxServiceProxy(linuxService); /** * Proxy类是专门完成代理的操作类,通过newProxyInstance方法为接口动态的生成实现类。 * 尽管我想指定一个目录, 但我核心是想调用LinuxService中的方法,因为我最终要调用的对象应该是 LinuxService下面的方法。 * 底层的实现我不在乎,在乎的是我调用的是LinuxService接口中的方法 */ /** * 三个参数的说明: * ClassLoader loader:类加载器 * Class<?>[] interfaces:得到全部的接口 * InvocationHandler h:得到InvocationHandler接口的子类实例 */ LinuxService asr = (LinuxService) Proxy .newProxyInstance(linuxService.getClass().getClassLoader(), linuxService.getClass().getInterfaces(), linuxServiceProxy); /** * 调用生成目录的方法,用返回的代理。 */ asr.mkdir(); } }

结果

=======代理对象开始工作======== 进入/Users/mac/Documents目录下后,创建一个新目录test,之后在/test中创建文件以及编辑文件! 我的核心实现是:创建一个文件夹! =======执行结束后跟我说一下========
最新回复(0)