jdk动态代理为什么要实现接口
前言
从代码角度解释jdk动态代理为什么一定要有实现接口
一、创建功能接口,实现类
接口
public interface User {
void doSomeThing();
}
接口实现
public class Student implements User{
@Override
public void doSomeThing() {
System.out.println("我是一个学生");
}
}
Handle处理器
public class UserHandle implements InvocationHandler {
private Object target;
public UserHandle(Object target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("doSomeThing")) {
System.out.println("人物介绍前处理一下子");
Object invoke = method.invoke(target,args);
System.out.println("人物介绍后处理一下子");
return invoke;
}
return method.invoke(target, args);
}
}
二、测试
1.jdk动态代理方式
public class ProxyTest {
public static void main(String[] args) {
Student student = new Student();
//直接拉姆达表达式也可以
User user1 =(User) Proxy.newProxyInstance(student.getClass().getClassLoader()
, student.getClass().getInterfaces()
, (proxy, method, args1) -> method.invoke(student,args1));
User user2 =(User) Proxy.newProxyInstance(student.getClass().getClassLoader()
, student.getClass().getInterfaces()
, new UserHandle(student));
user1.doSomeThing();
user2.doSomeThing();
System.out.println("sas");
//会生成代理类$Proxy0的class文件或者在vm参数里面加
//-Dsun.misc.ProxyGenerator.saveGeneratedFiles=true
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
}
}
反编译$Proxy0.class
public final class $Proxy0 extends Proxy implements User {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
//省略equals ,string,hashcode等方法
public final void doSomeThing() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
2.cglib动态代理方式
public class CgLibProxyTest {
public static void main(String[] args) {
//能将生成的代理class文件保存下来
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "./cglib");
//生成cglib增强器,相当于工厂类
Enhancer enhancer = new Enhancer();
//传入被代理的类
enhancer.setSuperclass(Student.class);
//构建cglib中被代理方法详情类
Callback callback = (MethodInterceptor) (obj, method, args1, proxy) -> {
Object result = null;
//增强
if (method.getName().equals("doSomeThing")) {
result = proxy.invokeSuper(obj, args1);
} else {
result = proxy.invokeSuper(obj, args1);
}
return result;
};
//将被代理方法详情对象传递给工厂类
enhancer.setCallback(callback);
//生成代理类
Student targetClass = (Student) enhancer.create();
targetClass.doSomeThing();
}
}
cglib生成的代理类
public class Student$$EnhancerByCGLIB$$2c909f28 extends Student implements Factory{
。。。。。
//省略
public final void doSomeThing() {
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$doSomeThing$0$Method, CGLIB$emptyArgs, CGLIB$doSomeThing$0$Proxy);
} else {
super.doSomeThing();
}
}
}
总结
- jdk动态生成的代理类是已经含有了一个父类Proxy ,通过父类去获取传递的InvocationHandle执行,java是单继承的,所以只能通过实现接口来实现doSomeThing()方法
- cglib动态代理生成的代理类是继承了Student类,子类重写父类方法的方式