JDK动态代理
定义接口:
public interface HelloWorld {
void sayHelloWorld();
}
实现代理类,继承自InvocationHandler:
public class JdkProxyDemo implements InvocationHandler {
//真实对象
private Object target = null;
//代理对象-获取被代理接口实例对象 - 即生成了一个代理类
//1.建立代理对象和真实对象的关系
Object bind(Object target) {
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
/**
* Description: 代理方法逻辑
*
* @param proxy :代理对象,即bind方法产生的对象
* @param method :当前调度方法
* @param args :当前方法参数
* @return java.lang.Object:代理结果返回
*/
//2.实现代理逻辑方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("进入代理逻辑方法");
System.out.println("在调用真实方法之前的服务...");
Object object = method.invoke(target, args);
System.out.println("在调用真实方法之后的服务...");
return object;
}
}
测试类:
public class JdkProxyTest {
public static void main(String[] args) {
//以下代码打印出代理类com/sun/proxy/$Proxy0.class
//原理是sun/misc/ProxyGenerator.class的generateProxyClass方法生成字节码后,判断了此标识位
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
JdkProxyDemo jdk = new JdkProxyDemo();
//绑定关系
HelloWorld proxy = (HelloWorld) jdk.bind(new HelloWorldImpl());
//此时的proxy是一个代理对象,他会进入代理类(即$Proxy0.class)的逻辑方法invoke里
//而代理类中的invoke方法,又调用了InvocationHandler接口的invoke方法...
proxy.sayHelloWorld();
}
}
生成的代理类:
public final class $Proxy0 extends Proxy implements HelloWorld {
private static Method m1;
private static Method m2;
private static Method m3;
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 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 void sayHelloWorld() throws {
try {
super.h.invoke(this, m3, (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"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("com.kyee.etltool.practice.designpattern.dynamicProxy.HelloWorld").getMethod("sayHelloWorld");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
CGLIB动态代理
需要代理的类:
public class HelloWorldImpl {
public void sayHelloWorld() {
System.err.println("hello world...");
}
}
CGLIB代理类:
public class CglibProxyDemo implements MethodInterceptor {
/**
* Description: 生成CGLIB代理对象
*
* @param cls :class类
* @return java.lang.Object
*/
public Object getProxy(Class cls) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(cls);//设置增强类型
enhancer.setCallback(this);//设定义代理逻辑对象为当前对象,要求当前对象实现MethodInterceptor
//生成并返回代理对象(封装在了拦截器的第一个参数里...)
//HelloWorldImpl$$EnhancerByCGLIB$$ba1f40a9@473b46c3
return enhancer.create();
}
/**
* Description:
*
* @param o :代理对象,
* @param method :方法
* @param objects :方法参数
* @param methodProxy :方法代理
* @return java.lang.Object
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("调用真实对象前");
//CGLIB反射调用真实方法
Object result = methodProxy.invokeSuper(o, objects);
System.out.println();
System.out.println("调用真实对象后。。。");
return result;
}
}
测试类:
public class CglibProxyTest {
public static void main(String[] args) {
//将生成的类放在c盘的这个路径下
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "C:\\codemaker");
CglibProxyDemo cglibProxyDemo = new CglibProxyDemo();
//生成代理对象,制定代理逻辑类
HelloWorldImpl h = (HelloWorldImpl) cglibProxyDemo.getProxy(HelloWorldImpl.class);
h.sayHelloWorld();
}
}
运行后可以看到输出:
CGLIB debugging enabled, writing to 'C:\codemaker'
调用真实对象前
hello world...
调用真实对象后。。。
对应文件夹下有三个class文件:
打开第二个可以看到:
public class HelloWorldImpl$$EnhancerByCGLIB$$ba1f40a9 extends HelloWorldImpl implements Factory {
private boolean CGLIB$BOUND;
public static Object CGLIB$FACTORY_DATA;
private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
private static final Callback[] CGLIB$STATIC_CALLBACKS;
private MethodInterceptor CGLIB$CALLBACK_0; //拦截器
private static Object CGLIB$CALLBACK_FILTER;
private static final Method CGLIB$sayHelloWorld$0$Method; //被代理方法
private static final MethodProxy CGLIB$sayHelloWorld$0$Proxy; //代理方法
...
static void CGLIB$STATICHOOK1() {
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
CGLIB$emptyArgs = new Object[0];
//代理类
Class var0 = Class.forName("com.kyee.etltool.practice.designpattern.dynamicProxy.impl.HelloWorldImpl$$EnhancerByCGLIB$$ba1f40a9");
//被代理类
Class var1;
Method[] var10000 = ReflectUtils.findMethods(new String[]{"equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (var1 = Class.forName("java.lang.Object")).getDeclaredMethods());
CGLIB$equals$1$Method = var10000[0];
CGLIB$equals$1$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$1");
CGLIB$toString$2$Method = var10000[1];
CGLIB$toString$2$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$2");
CGLIB$hashCode$3$Method = var10000[2];
CGLIB$hashCode$3$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$3");
CGLIB$clone$4$Method = var10000[3];
CGLIB$clone$4$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$4");
CGLIB$sayHelloWorld$0$Method = ReflectUtils.findMethods(new String[]{"sayHelloWorld", "()V"}, (var1 = Class.forName("com.kyee.etltool.practice.designpattern.dynamicProxy.impl.HelloWorldImpl")).getDeclaredMethods())[0];
CGLIB$sayHelloWorld$0$Proxy = MethodProxy.create(var1, var0, "()V", "sayHelloWorld", "CGLIB$sayHelloWorld$0");
}
final void CGLIB$sayHelloWorld$0() {
super.sayHelloWorld();
}
public final void sayHelloWorld() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
//调用拦截器
var10000.intercept(this, CGLIB$sayHelloWorld$0$Method, CGLIB$emptyArgs, CGLIB$sayHelloWorld$0$Proxy);
} else {
super.sayHelloWorld();
}
}
final boolean CGLIB$equals$1(Object var1) {
return super.equals(var1);
}
...
从代理对象反编译源码可以知道,代理对象继承于被代理类,拦截器调用intercept()方法,intercept()方法由自定义CglibProxyDemo implements MethodInterceptor实现,所以,最后调用CglibProxyDemo中的intercept()方法,从而完成了由代理对象访问到目标对象的动态代理实现。