本文阅读量
代理模式#
为什么要学习代理模式#
代理模式是SpringAOP的底层
代理模式的分类#
- 静态代理
- 动态代理
静态代理#
角色分析
- 抽象接口:真实类和代理类都要实现的接口
- 真实类:被代理的类
- 代理类:代理真实类,一般代理后会有一些附属操作
- 客户类:访问代理类
实例代码#
package top.longlone;
public interface Rent {
public void rent();
}
package top.longlone;
public class Landlord implements Rent {
public void rent(){
System.out.println("租房子");
}
}
````
```java
package top.longlone;
public class LandlordProxy implements Rent {
public Rent landlord;
public LandlordProxy() {
this.landlord = new Landlord();
}
public void rent() {
this.landlord.rent();
System.out.println("收中介费");
}
}
````
```java
package top.longlone;
public class Client {
public static void main(String[] args) {
Rent landlordProxy = new LandlordProxy();
landlordProxy.rent();
}
}
代理模式的特点#
优点:
- 可以使真实类更加纯粹,不再需要关注一些公共服务
- 实现公共服务交给代理角色,实现了业务分工
- 客户类只能访问到代理类,隐藏了真实类
- 方便扩展和集中管理
缺点:
- 代理类和真实类的关系在编译时确定,所以一个真实类就需要一个代理类
动态代理#
动态代理分为两类:基于接口的动态代理和基于类的动态代理
- 基于接口: JDK动态代理
- 基于类: cglib
- java字节码实现: javasist
这里先了解JDK自带的动态代理
需要了解2个类:
- Proxy
:用于创建代理类的类
- InvocationHandler
:代理实例调用方法时的一个接口,通过在invoke方法里编写额外代码实现附属功能
实例代码#
package top.longlone;
// 抽象接口,抽象出rent这个方法
public interface Rent {
public void rent();
}
package top.longlone;
// 真实类,实现了rent方法
public class Landlord implements Rent {
public void rent(){
System.out.println("租房子");
}
}
package top.longlone;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 这里将Porxy和InvocationHandler合二为一
public class LandlordInvocationHandler implements InvocationHandler {
//真实类的实例,即被代理的实例
private Object obj;
public Object getObj() {
return obj;
}
public void setObj(Object obj) {
this.obj = obj;
}
public LandlordInvocationHandler() {
}
public LandlordInvocationHandler(Object obj) {
this.obj = obj;
}
// 获取代理类
public Rent getProxy() {
return (Rent) Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
}
// 重写InvocationHandler的invoke方法,在调用Rent接口的任何方法前前增加一句输出
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Running method: " + method.getName());
Object result = method.invoke(obj, args);
return result;
}
}
package top.longlone;
public class Client {
public static void main(String[] args) {
// 创建真实类的实例,即被代理的实例
Landlord landlord = new Landlord();
// 创建自己编写的InvocationHandler,并传入被代理的实例
LandlordInvocationHandler handler = new LandlordInvocationHandler(landlord);
// 获取代理类
Rent landlordProxy = handler.getProxy();
// 调用代理类的rent方法
landlordProxy.rent();
/* Output:
Running method: rent
租房子
*/
}
}
代理模式和装饰器模式的区别#
装饰器模式关注于在一个对象上动态的添加方法,然而代理模式关注于控制对对象的访问。换句话 说,用代理模式,代理类可以对它的客户隐藏一个对象的具体信息。因此,当使用代理模式的时候,我们常常在一个代理类中创建一个对象的实例。并且,当我们使用装饰器模 式的时候,我们通常的做法是将原始对象作为一个参数传给装饰者的构造器。
使用代理模式,代理和真实对象之间的的关系通常在编译时就已经确定了,而装饰者能够在运行时递归地被构造。
总结#
代理模式是SpringAOP的底层,分为静态代理和动态代理,同时了解了JDK自带的动态代理的编写。