假设我们有一个叫做FileSystem接口,UnixFileSystem类实现了FileSystem接口,我们可以使用JDK动态代理的方式给FileSystem的接口方法执行前后都添加日志输出。
com.anbai.sec.proxy.FileSystem示例代码:
package com.anbai.sec.proxy;import java.io.File;import java.io.Serializable;/*** Creator: yz* Date: 2020/1/14*/public interface FileSystem extends Serializable {String[] list(File file);}
com.anbai.sec.proxy.UnixFileSystem示例代码:**
package com.anbai.sec.proxy;import java.io.File;/*** Creator: yz* Date: 2020/1/14*/public class UnixFileSystem implements FileSystem {/* -- Disk usage -- */public int spaceTotal = 996;@Overridepublic String[] list(File file) {System.out.println("正在执行[" + this.getClass().getName() + "]类的list方法,参数:[" + file + "]");return file.list();}}
com.anbai.sec.proxy.JDKInvocationHandler示例代码:
package com.anbai.sec.proxy;import java.io.Serializable;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;/*** Creator: yz* Date: 2020/1/14*/public class JDKInvocationHandler implements InvocationHandler, Serializable {private final Object target;public JDKInvocationHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 为了不影响测试Demo的输出结果,这里忽略掉toString方法if ("toString".equals(method.getName())) {return method.invoke(target, args);}System.out.println("即将调用[" + target.getClass().getName() + "]类的[" + method.getName() + "]方法...");Object obj = method.invoke(target, args);System.out.println("已完成[" + target.getClass().getName() + "]类的[" + method.getName() + "]方法调用...");return obj;}}
com.anbai.sec.proxy.FileSystemProxyTest示例代码:
package com.anbai.sec.proxy;import java.io.File;import java.lang.reflect.Proxy;import java.util.Arrays;/*** Creator: yz* Date: 2020/1/14*/public class FileSystemProxyTest {public static void main(String[] args) {// 创建UnixFileSystem类实例FileSystem fileSystem = new UnixFileSystem();// 使用JDK动态代理生成FileSystem动态代理类实例FileSystem proxyInstance = (FileSystem) Proxy.newProxyInstance(FileSystem.class.getClassLoader(),// 指定动态代理类的类加载器new Class[]{FileSystem.class}, // 定义动态代理生成的类实现的接口new JDKInvocationHandler(fileSystem)// 动态代理处理类);System.out.println("动态代理生成的类名:" + proxyInstance.getClass());System.out.println("----------------------------------------------------------------------------------------");System.out.println("动态代理生成的类名toString:" + proxyInstance.toString());System.out.println("----------------------------------------------------------------------------------------");// 使用动态代理的方式UnixFileSystem方法String[] files = proxyInstance.list(new File("."));System.out.println("----------------------------------------------------------------------------------------");System.out.println("UnixFileSystem.list方法执行结果:" + Arrays.toString(files));System.out.println("----------------------------------------------------------------------------------------");boolean isFileSystem = proxyInstance instanceof FileSystem;boolean isUnixFileSystem = proxyInstance instanceof UnixFileSystem;System.out.println("动态代理类[" + proxyInstance.getClass() + "]是否是FileSystem类的实例:" + isFileSystem);System.out.println("----------------------------------------------------------------------------------------");System.out.println("动态代理类[" + proxyInstance.getClass() + "]是否是UnixFileSystem类的实例:" + isUnixFileSystem);System.out.println("----------------------------------------------------------------------------------------");}}
程序执行结果:
动态代理生成的类名:class com.sun.proxy.$Proxy0----------------------------------------------------------------------------------------动态代理生成的类名toString:com.anbai.sec.proxy.UnixFileSystem@194d6112----------------------------------------------------------------------------------------即将调用[com.anbai.sec.proxy.UnixFileSystem]类的[list]方法...正在执行[com.anbai.sec.proxy.UnixFileSystem]类的list方法,参数:[.]已完成[com.anbai.sec.proxy.UnixFileSystem]类的[list]方法调用...----------------------------------------------------------------------------------------UnixFileSystem.list方法执行结果:[javaweb-sec.iml, javaweb-sec-source, pom.xml, README.md, .gitignore, gitbook, .git, jni, .idea]----------------------------------------------------------------------------------------动态代理类[class com.sun.proxy.$Proxy0]是否是FileSystem类的实例:true----------------------------------------------------------------------------------------动态代理类[class com.sun.proxy.$Proxy0]是否是UnixFileSystem类的实例:false----------------------------------------------------------------------------------------
