通常jdk代理有两种,一种静态一种动态。
JDK静态代理
就是继承或者实现接口,编译期生成一份之后执行的class文件
public class Employee {
public void work() {
System.out.println("work");
}
}
public class SuperEmployee extends Employee{
@Override
public void work() {
System.out.println("super======");
super.work();
System.out.println("super======");
}
}
public class TestStaticProxy {
public static void main(String[] args) {
SuperEmployee superEmployee = new SuperEmployee();
superEmployee.work();
}
}
静态代理,执行上,直接执行最终的代理对象。 讲到底就是重写。
JDK动态代理
先写个测试
public interface PersonTest {
void giveMoney();
}
public class Student implements PersonTest {
private String name;
public Student(String name) {
this.name = name;
}
@Override
public void giveMoney() {
System.out.println(name + "上交班费50元");
}
}
public class TestInvocationHandler<T> implements InvocationHandler {
//invocationHandler持有的被代理对象
T target;
public TestInvocationHandler(T target) {
this.target = target;
}
/**
* proxy:代表动态代理对象
* method:代表正在执行的方法
* args:代表调用目标方法时传入的实参
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理执行" +method.getName() + "方法");
Object result = method.invoke(target, args);
MonitorUtil.finish(method.getName());
return result;
}
}
public class ProxyTest {
public static void main(String[] args) {
//创建一个实例对象,这个对象是被代理的对象
Person zhangsan = new Student("张三");
//创建一个与代理对象相关联的InvocationHandler
InvocationHandler testHandler = new TestInvocationHandler<Person>(zhangsan);
//创建一个代理对象stuProxy来代理zhangsan,代理对象的每个执行方法都会替换执行Invocation中的invoke方法
Person testProxy = (Person) Proxy.newProxyInstance(Person.class.getClassLoader(), new Class<?>[]{Person.class}, testHandler);
//代理执行上交班费的方法
testProxy.giveMoney();}
}
使用上,我们所实现TestInvocationHandler 需要将我们的目标类作为属性设置进来
对应所生成的class文件,使用jdk动态代理会生成新的class文件。
调用的最终对象就是是由这个class文件生成的对象。
我们看一下新的class文件内容
public final class $Proxy0 extends Proxy implements PersonTest {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
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("proxy.PersonTest").getMethod("giveMoney");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
public final void giveMoney() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
}
public class Proxy implements java.io.Serializable {
protected InvocationHandler h;
}
结论
从所生成的代理类class文件,初始化的方法既继承了我们的Proxy类,又实现了我们需要增强的接口。在生成的代理class文件中,我们实现的giveMoeny方法,直接调用了我们所实现的InvocationHandler 的invoke方法,再到里面,通过反射,执行我们自己实现的giveMeney方法。 可以看出,动态代理对于静态代理而言,动态代理可以同一个加强方法应用在不同类上。