JDK 中提供了 Proxy 类实现动态代理,动态代理实现的主要方式是其中的一个静态方法
loader:类加载器
interfaces:被代理对象实现的接口,并且被代理对象一定要实现接口
h:处理器接口,需要实现invoke方法具体实现需要增强的功能
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
处理器需要实现的方法
proxy:代理对象本身
method:被代理对象的方法对象
args:被代理对象方法执行所需要的参数
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("前置处理。。。");
Object invoke = method.invoke(userService, args);
System.out.println("后置处理。。。");
return invoke;
}
代理类是在程序运行过程中,JVM 动态生成的类。对于处理器的几个参数为什么是这样,我们可以设置一些参数,将JVM生成的代理类输出到文件中,我们可以查看代理类字节码文件。
举例如下
接口
public interface UserService {
String run();
void hello();
}
实现类
public class UserServiceImpl implements UserService{
@Override
public String run() {
System.out.println("UserService run........");
return "run";
}
@Override
public void hello() {
System.out.println("hello");
}
}
测试:在main方法执行的时候添加语句 : System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
public class MainRun {
public static void main(String[] args) {
System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
UserService userService = new UserServiceImpl();
UserService userServiceProxy = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object invoke = method.invoke(userService, args);
System.out.println("After method handle...");
return invoke;
}
});
String run = userServiceProxy.run();
System.out.println("run = " + run);
}
}
运行main方法,可以发现项目中多出代理对象字节码文件
如果没有出现,则通过main方法入口参数进行设置
添加-Dsun.misc.ProxyGenerator.saveGeneratedFiles=true即可
字节码文件通过反编译技术,我们可以查看源码。
public final class $Proxy0 extends Proxy implements UserService {
private static Method m1;
private static Method m3;
private static Method m4;
private static Method m2;
private static Method m0;
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String run() throws {
try {
return (String)super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void hello() throws {
try {
super.h.invoke(this, m4, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m3 = Class.forName("pers.yang.service.UserService").getMethod("run");
m4 = Class.forName("pers.yang.service.UserService").getMethod("hello");
m2 = Class.forName("java.lang.Object").getMethod("toString");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
通过查看源码,我们可以看到,静态成员变量都是Method对象,静态代码块通过反射技术进行注入。
生成的每一个方法的格式都大同小异
super.h代表的就是 InvocationHandler 对象
this:代理对象
method:被代理对象的方法
Object[]:被代理对象方法参数
和我们重写 InvocationHandler invoke方法参数一一对应
这时本人对 Java 中动态代理对象的简单理解,还请各位大佬指教!