一·静态代理模式
房东要出租房子,中介代理房东,并有额外的操作,他们共同实现一个Rent接口。
Rent接口:
public interface Rent {
void rent();
}
Host类:
public class Host implements Rent{
@Override
public void rent() {
System.out.println("房东要租房子");
}
}
Proxy代理类:
public class Proxy implements Rent{
private Host host;
public Proxy() {
}
public Proxy(Host host) {
this.host = host;
}
@Override
public void rent() {
seeHouse();
host.rent();
}
private void seeHouse(){
System.out.println("中介带你看房子");
}
}
Client类:
public class Client {
public static void main(String[] args) {
Host host = new Host();
Proxy proxy = new Proxy(host);
proxy.rent();
}
}
中介代理了房东,并有额外的看房操作。
但是,静态代理有很大的弊端,一个真实对象就需要有一个对应的代理类,代码需要重复很多次。
二·动态代理
动态代理是基于反射实现的,可以动态的对真实对象生成代理对象。
Rent类与Host类不变,代理类由InvocationHandler 产生,注意动态代理代理的是一个接口,外部调用只能用接口调用。
public class ProxyInvokeHandler implements InvocationHandler {
private Host host;
public void setHost(Host host) {
this.host = host;
}
//生成代理对象
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(), host.getClass().getInterfaces(),this);
}
//处理代理对象调用的方法,并返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(host,args);
return result;
}
}
可以将动态代理抽取成一个工具类,可以对任意的对象的接口做代理。
public class ProxyInvocationHandlerUtil 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 {
Object result = null;
System.out.println("执行之前添加逻辑");
long startTime = System.currentTimeMillis();
for (int i = 0; i < 100; i++) {
result = method.invoke(target, args);
}
System.out.println("执行之后添加逻辑");
long endTime = System.currentTimeMillis();
System.out.println("共花"+(endTime-startTime)+"ms");
return result;
}
}
Client类:
public class Client {
public static void main(String[] args) {
ProxyInvocationHandlerUtil pih = new ProxyInvocationHandlerUtil();
Host host = new Host();
pih.setTarget(host);
Rent proxy = (Rent) pih.getProxy();
proxy.rent();
}
}