3.1、介绍
代理模式:为一个对象提供一个替身,以控制对这个对象的访问。即通过代理对象访问目标对象。
代理模式优点:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。
被代理的对象:远程对象、创建开销大的对象、需要安全控制的对象。
代理模式主要有三种形式:
- 静态代理模式(基于接口实现)
- 动态代理模式(基于接口实现,又称为JDK代理、接口代理)
- Cglib代理模式(可以在内存动态地创建对象,而不需要实现接口,它是属于动态代理范畴)。
这种类型的设计模式属于结构型模式。
下面介绍静态代理模式和动态代理模式。
3.2、静态代理模式
静态代理在使用时,需要定义接口或者父类,被代理对象(即目标对象)与代理对象一起实现相同的接口或者继承相同的父类。
举例:有房东要通过中介将房屋出租。
首先要有接口 Rent.java
,里面有方法 rent()
出租房屋:
public interface Rent {
// 出租房屋
void rent();
}
然后是被代理对象房东 Host.java
实现接口 Rent.java
:
public class Host implements Rent {
@Override
public void rent() {
System.out.println("有房东要出租房屋");
}
}
同样的,代理对象中介 Intermediary.java
也要实现接口 Rent.java
:
public class Intermediary implements Rent {
private Host host;
public Intermediary(Host host) {
this.host = host;
}
@Override
public void rent() {
System.out.println("中介开始代理房东………");
// 交给中介把房子租出去
host.rent();
System.out.println("代理结束……………………");
}
}
最后,客户端 Client.java
实现中介代理房东将房屋出租:
public class Client {
public static void main(String[] args) {
// 房东通过中介把房子租出去
Host host = new Host();
Intermediary intermediary = new Intermediary(host);
intermediary.rent();
}
}
运行结果如图:
总结:定义一个接口,让被代理对象和代理对象都实现该接口,代理对象中是用的静态代理方式实现接口,最后调用代理对象的方法调用目标对象。重点在被代理对象和代理对象要实现相同的接口,然后通过调用相同的方法来调用被代理对象的方法。
3.3、动态代理模式
在动态代理模式中,被代理对象(即目标对象)仍需要实现接口,但代理对象不需要实现接口。
代理对象的生成,是利用 JDK 的 API 动态地在内存中构建代理对象。因此动态代理也叫做JDK代理、接口代理。
同样举例:有房东要通过中介将房屋出租。
接口 Rent.java
和目标对象房东 Host.java
的代码同上述静态代理中的一样。
中介 Intermediary.java
没有实现接口 Rent.java
,使用的方法 newProxyInstance()
:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Intermediary {
private Object host;
public Intermediary(Object host) {
this.host = host;
}
// 给目标对象生成一个代理对象
public Object getProxyInstance(){
return Proxy.newProxyInstance(host.getClass().getClassLoader(),
host.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("动态代理开始…………");
Object result = method.invoke(host, args);
System.out.println("结束动态代理…………");
return result;
}
});
}
}
客户端 Client.java
实现中介代理房东将房屋出租:
public class Client {
public static void main(String[] args) {
Rent host = new Host();
Rent intermediary = (Rent)new Intermediary(host).getProxyInstance();
// 通过代理对象,调用目标对象的方法
intermediary.rent();
}
}
总结:代理类所在包是 java.lang.reflect.Proxy
;JDK实现代理只需要使用 newProxyInstance()
方法,但是该方法需要接收三个参数,完整的写法是 static object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
,三个参数的意思分别是:
ClassLoader loader
:指定当前目标对象使用的类加载器,获取加载器的方法。Class<?>[] interfaces
:目标对象实现的接口类型,使用泛型方法确认类型。InvocationHandler h
:事件处理,执行目标对象的方法时,会出发事件处理器方法,会把当前执行的目标对象方法作为参数传入。