JDK动态代理是面向接口的。这是很多框架的基础。
JDK动态代理的原理是接口的实现, 所以接口一定要存在, 而且只能代理接口存在的方法.
首先动态代理类要实现InvocationHandler
接口,该接口只有一个方法。
public Object invoke(Object proxy, Method method, Object[] args)
// proxy 参数是代理对象本身,在整个动态代理实现的过程中没有用到。
// method是代理对象调用的方法,args是方法的参数
需求:现在有一个房东host要出租房子,但是自己又非常懒,不想自己带人看房,议价之类,所以想让中介帮其租房子,此时中介就是个代理。
由于JDK动态代理是面向接口的,所以先有一个Rent接口代表出租的动作。
package com.ldt.pojo;
public interface Rent {
void rent();
}
再有一个房东。
package com.ldt.pojo;
public class Host implements Rent{
@Override
public void rent() {
System.out.println("房东要把房子租出去");
}
}
再有一个动态代理类。
package com.ldt.pojo;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyInvocationHandler implements InvocationHandler {
// 被代理的接口
private Object target;
public void setTarget(Object target) {
this.target = target;
}
// 动态生成代理类
public Object getProxy() {
return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
// 处理代理实例,并返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
seeHouse();
Object result = method.invoke(target, args);
hetong();
return result;
}
private void seeHouse() {
System.out.println("中介带看房子");
}
private void hetong() {
System.out.println("签合同");
}
}
需要注意的是Proxy.newProxyInstance
方法,该方法是动态生成代理对象的,第一个参数是classloader,第二个参数是要代理的类的接口,此处是Rent接口,第三个参数是handler对象本身。可以看出handler类并不是代理类,只是生成代理需要的一个元素,我们实现的invoke方法也不是代理类的方法,而是代理类要调用的方法,就是说代理类中会调用handler.invoke方法。
开始测试:
这里有一个client要来租房子。
package com.ldt.pojo;
public class Client {
public static void main(String[] args) {
Host host = new Host();
ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();
proxyInvocationHandler.setTarget(host);
// 生成代理类
Rent proxy = (Rent) proxyInvocationHandler.getProxy();
// 调用代理类的rent方法,就是这个方法中调用了handler的invoke方法
proxy.rent();
}
}
由于代理对象是动态生成的,如何通过调用rent方法进而调用invoke不是一个显示的过程,但是查看源码可以知道,Proxy.newProxyInstance
方法在生成代理对象时,动态的实现了rent方法,并且在rent方法中调用了handler的invoke方法。