JDK动态代理
动态代理区别于静态代理,代理类在运行时生成。JDK 提供InvocationHandler
接口和Proxy
类实现动态代理。
由于Proxy生成代理类方法
Proxy. newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h);需要传入带实现的接口方法interfaces
,JDK动态代理需要实现接口才能实现。
代码实现:
定义接口
public interface Subject{
void doMethod();
}
实现类:
public class RealSubject implements Subject{
public void doMethod(){
System.out.println("JDK Proxy Do Method Real!");
}
}
代理类:
public class ProxyService implements InvocationHandler{
private Subject subject;
public Object getInstance(Subject subject){
this.subject=subject;
Class<?> clazz=subjcet.getClass();
return Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("JDK Proxy Do Before!");
method.invoke(this.subject,args);
System.out.println("JDK Proxy Do After!");
return null;
}
}
测试类:
public static void main(String[] args) {
Subject subject= (Subject) new ProxyService().getInstance(new RealSubject());
subject.doMethod();
/**
* 保存jdk动态生成代码查看
*/
byte[] batyes = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{Subject.class});
try (FileOutputStream out = new FileOutputStream("E://$Proxy0.class")) {
out.write(batyes);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
测试输出:
JDK Proxy Do Before!
JDK Proxy Do Method Real!
JDK Proxy Do After!
代理生成源码,JDK动态代理生成的类以$Proxy0命名。具体代码生成的过程请查看Proxy.newProxyInstance
源码。
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
import com.ognice.proxy.jdkproxy.Subject;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
//实现了 Subject接口
public final class $Proxy0 extends Proxy implements Subject {
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 {
//...
}
public final String toString() throws {
//...
}
// 目标方法,h为传入的ProxyService,m3由静态代码块初始化
public final void doMethod() 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 {
//...
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
// 通过反射获取目标实现方法m3
m3 = Class.forName("com.ognice.proxy.jdkproxy.Subject").getMethod("doMethod");
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动态代理
JDK动态代理需要实现接口才能实现,cglib对JDK动态代理的补充,但对于final类无法实现代理,因为cglib实现动态生成被代理类的子类形式。cglibt代理类通过实现MethodInterceptor
接口实现代理逻辑
引入依赖
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.7</version>
</dependency>
被代理类
public class TargetService{
public void doMethod(){
System.out.printIn("Real Method!")
}
}
代理类实现MethodInterceptor
接口
public class ProxyService implements MethodInterceptor{
public Object getInstance(Class<?> clazz) {
//代理类生成
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(clazz);
// 配置回调
enhancer.setCallback(this);
return enhancer.create();
}
/**
* 重写方法拦截在方法前和方法后加入业务
* Object obj为目标对象
* Method method为目标方法
* Object[] params 为参数,
* MethodProxy proxy CGlib方法代理对象
*/
@Override
public Object intercept(Object obj, Method method, Object[] params,
MethodProxy proxy) throws Throwable {
System.out.println("CGlib Proxy Before");
proxy.invokeSuper(obj, params);
System.out.println("CGlib Proxy AFter");
return result;
}
}
测试类
public static void main(String[] args) {
TargetService targetService = (TargetService) new
ProxyService().getInstance(TargetService.class);
targetService.doMethod();
System.out.println(targetService.getClass());
}
输出
CGlib Proxy Before
Real Method!
CGlib Proxy AFter
class com.ognice.proxy.cglibproxy.TargetService$$EnhancerByCGLIB$$d9637b11
可以看出最终生成的TargetService
实例的类为cglib动态生成的类。原理是动态生成一个类继承了被代理类,调用invokeSuper
方法实现方法调用。
网友评论