Spring-AOP_03-动态代理-JDK动态代理
2018-06-08 本文已影响0人
rock_fish
JDK动态代理是这样一种Class:
- 在运行时生成class,
- 在生成他时,必须提供一组interfaces给它,然后该class就会声明它实现了这些interfaces.因此我们可以将该class的实例当做这些interfaces中的任何一个来用.
- 当然这个动态代理其实就是一个Proxy,它不会代替你做实质性的工作,在生成他的实例时,你必须提供一个handler,由它接管实际的工作.
个人感觉这么去理解JDK动态代理:
- 1.谁按照什么规则,提供一个什么
- 2.替谁,具体做什么事.
映射一下
1.类加载器按照给定的接口规则,提供(创建)了一个代理类.
2.替目标类(被代理的类),具体做InvocationHandler实现的逻辑.
JDK动态代理 只能代理接口,核心代码理解:
1.类加载器按照给定的接口规则,提供(创建)了一个代理类.
//返回代理类的一个实例,返回后的代理类可以当做被代理类使用
static Object newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)
loader:类加载器,用于创建代理类实例
interfaces:实现的接口,标识代理类实现了哪些接口
invocationHandler:实际代理内容的实现.
2.替目标类(被代理的类),具体做InvocationHandler实现的逻辑.
//InvocationHandler 类中的方法
public Object invoke(Object obj,Method method,Object[] args)
obj: 一般指代理对象 代理对象已经被创建了,传递到这里,
method:被代理的方法,指定的接口中的方法
args:该方法的参数数组.实际方法调用时候的实际参数数组
上述两个方法位于java.lang.reflect包下,从包名看出属于反射的范畴.
public interface Subject {
public void request();
}
public class RealSubject implements Subject {
public void request() {
System.out.println("From real subject");
}
}
public class DynamicSubject implements InvocationHandler {
private Object sub;
public DynamicSubject(Object obj){
this.sub = obj;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//proxy 是代理对象,不是真实对象.
System.out.println("before calling: " + method);
//这里使用的sub是被代理的对象的实例.
method.invoke(sub,args);//sub:对象(对应到面向对象中实例方法中的this) args:方法参数(对应到类中的实例方法运行时参数)
System.out.println(args == null);
System.out.println("after calling: " + method);
return null;
}
}
//JDK动态代理实现步骤
//1.创建一个实现接口InvocationHandler的类,它必须实现invoke方法
//2.创建被代理的类以及接口(类实现此接口)因为JDK动态代理的规则,必须有接口
//3.通过Proxy的静态方法 newProxyInstance()创建一个代理
//4.通过代理调用方法.
public class TestProxy {
public static void main(String[] args) {
RealSubject realSubject = new RealSubject();
InvocationHandler handler = new DynamicSubject(realSubject);
Class<?> classType = handler.getClass();
Class<?>[] interfaces = realSubject.getClass().getInterfaces();
Subject subject = (Subject) Proxy.newProxyInstance(classType.getClassLoader(),interfaces,handler);
subject.request();
System.out.println(subject.getClass());
}
}
运行结果:
before calling: public abstract void com.zto.learn.Subject.request()
From real subject
true
after calling: public abstract void com.zto.learn.Subject.request()
class com.sun.proxy.$Proxy0
通过这种方式,被代理的对象(RealSubject)可以在运行时动态概念,需要控制的接口(Subject接口)可以在运行时改变,控制的方式(DynamicSubject类)也 可以动态改变,从而实现了非常灵活的动态代理关系.