一个对象(客户端)不能或不想直接引用另一个对象(目标对象),这时候就需要一个中介对象,这个中介对象在中间启到了代理作用(房屋中介),为客户端对象提供一种代理去控制访问目标对象。
1、静态代理
静态代理实现一共涉及3个角色和一个客户端:
(1)主题角色:Interface,通过真实角色和真实角色的共同操作属性抽取的一个角色(租赁角色)
/**
* 抽象角色(租赁角色)
*/
public interface Rent {
public void rentHouser();
}
(2)真实角色:Entity,目标对象,实现抽象角色类(真实的房主)
/**
* 真实角色(房主角色)
*/
public class RealUser implements Rent {
public void rentHouser() {
System.out.println("realUser:我有一套房子需要出租");
}
}
(3)代理角色:Entity,代理对象,实现抽象角色类,另外包括其他的一些操作(中介)
/**
* 代理角色(中介)
*/
public class ProxyUser implements Rent {
// 引入真实对象
private RealUser realUser;
// 构造代理的真实对象
public ProxyUser(RealUser realUser) {
this.realUser = realUser;
}
// 代理真实对象的操作
public void rentHouser() {
seeHoser();
realUser.rentHouser();
sign();
}
// 中介的其他的操作
public void seeHoser(){
System.out.println("中介带着看房");
}
// 中介的其他操作
public void sign(){
System.out.println("在中介签订合同");
}
}
(4)客户端对象:service,真正的调用者,通过代理对象间接控制真实对象的操作
/**
* 客户端(调用者)
*/
public class ClientUser {
public static void main(String[] args) {
ProxyUser proxyUser = new ProxyUser(new RealUser());
proxyUser.rentHouser();
}
}
注意:静态代理只能对一种类型进行代理(代理类是手动创建的)
2、动态代理(AOP底层原理)
动态代理是
代理模式
的一种实现方式,代理模式除了动态代理还有静态代理
,只不过静态代理能够在编译时期确定类的执行对象,而动态代理只有在运行时才能够确定执行对象是谁。代理可以看作是对最终调用目标的一个封装,我们能够通过操作代理对象来调用目标类,这样就可以实现调用者和目标对象的解耦合
和静态代理类的区别:动态代理类是通过反射生成的,而不是固定的
2.1 实现方式
- 基于接口:JDK的接口实现
- 基于类:cglib实现
- 基于类:javasist实现
2.2 基于JDK的接口实现动态代理
实现顺序:
1. 创建代理角色(接口)
public interface Rent {
public void rent();
}
2.创建真实角色(类)
public class Host implements Rent{
public void rent() {
System.out.println("房主要租房子");
}
}
3. 创建生成动态代理类程序(InvocationHandler)
public class MyInvokeHandler implements InvocationHandler {
private Rent rent;
public MyInvokeHandler(Rent rent) {
this.rent = rent;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
see();
Object result = method.invoke(rent, args);
sign();
return result;
}
public void see(){
System.out.println("看房子");
}
public void sign(){
System.out.println("签合同");
}
}
4. 创建动态代理类(Proxy.newProxyInstance(pram1,pram2,pram3))
// 创建真实角色
Host host = new Host();
// 创建代理角色
MyInvokeHandler myInvokeHandler = new MyInvokeHandler(host);
Rent rent = (Rent) Proxy.newProxyInstance(myInvokeHandler.getClass().getClassLoader(),
host.getClass().getInterfaces(),
myInvokeHandler);
5.代理类调用接口
rent.rent();
重点/关键点:
(1)InvocationHandler 类:
动态代理处理程序,主要来实现invoke方法,调用代理角色的实现方法
(2)invoke(Object proxy, Method method, Object[] args) 中的三个参数
method.invoke(代理角色,args)
(3)调用动态代理类过程 :Proxy.newProxyInstance(loader, interfaces, handler);
loader:动态代理类处理程序的类加载器
interfaces:代理角色或真实角色的所有接口
handler:动态代理类处理类