代理模式
代理模式介绍
分类
- 静态代理
- 动态代理
定义
由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。
优点
- 可以使真实角色操作更加纯粹,不需要去关心一些公共业务。
- 公共业务交给代理角色处理,实现业务的分工。
- 公共业务发生扩展时,方便集中管理。
缺点
- 一个真实角色会产生一个代理角色,代码量翻倍。
步骤
- 定义代理的接口
- 被代理的类
- 代理类
- 客户端访问代理类
代理模式结构与实现
结构
抽象主题(Subject)类:通过接口或抽象类声明真实主题和代理对象实现的业务方法。
真实主题(Real Subject)类:实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象。
代理(Proxy)类:提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制或扩展真实主题的功能。

静态代理
// 抽象主题
interface Subject {
void Request();
}
// 真实主题
class RealSubject implements Subject {
@Override
public void Request() {
System.out.println("访问真实主题方法...");
}
}
// 代理
class Proxy implements Subject {
private RealSubject realSubject;
public Proxy(RealSubject realSubject) {
this.realSubject = realSubject;
}
@Override
public void Request() {
if (realSubject == null) {
System.out.println("该代理还为与真实目标组合");
return;
}
preRequest();
realSubject.Request();
postRequest();
}
public void preRequest() {
System.out.println("访问真实主题之前的预处理。");
}
public void postRequest() {
System.out.println("访问真实主题之后的后续处理。");
}
}
public class ProxyTest {
public static void main(String[] args) {
Proxy proxy = new Proxy(new RealSubject());
proxy.Request();
/*
* 访问真实主题之前的预处理。
* 访问真实主题方法...
* 访问真实主题之后的后续处理。
*/
}
}
示例1:租房
Subject:租房 Rent
Real Subject:房东 LandLord
Proxy:中介 Realtor

// 抽象主题:租房
interface Rent {
void rent();
}
// 真实主题:房东
class Landlord implements Rent {
@Override
public void rent() {
System.out.println("房屋租借");
}
}
// 代理:房屋中介
class Realtor implements Rent {
private Landlord landlord;
public Realtor(Landlord landlord) {
this.landlord = landlord;
}
@Override
public void rent() {
if (landlord == null) {
System.out.println("该中介还未与房东合作");
}
preRent();
landlord.rent();
postRent();
}
public void preRent() {
System.out.println("前期介绍房屋");
}
public void postRent() {
System.out.println("后期房屋维权");
}
}
public class RentProxyTest {
public static void main(String[] args) {
Rent rent = new Realtor(new Landlord());
rent.rent();
/*
前期介绍房屋
房屋租借
后期房屋维权
*/
}
}
示例2 日志
Subject:增删改查服务 Service
RealSubject:服务实现类 ServiceImpl
Proxy:服务代理类 ServiceProxy
// 抽象主题:增删改查服务
interface Service {
void create();
void delete();
void update();
void retrieve();
}
// 真实主题:服务实现类
class ServiceImpl implements Service {
@Override
public void create() {
System.out.println("增!");
}
@Override
public void delete() {
System.out.println("删");
}
@Override
public void update() {
System.out.println("改");
}
@Override
public void retrieve() {
System.out.println("查");
}
}
// 代理:服务代理类
class ServiceProxy implements Service {
private ServiceImpl service;
public void setService(ServiceImpl service) {
this.service = service;
}
@Override
public void create() {
if (log("create")) {
service.create();
}
}
@Override
public void delete() {
if (log("delete")) {
service.delete();
}
}
@Override
public void update() {
if (log("update")) {
service.update();
}
}
@Override
public void retrieve() {
if (log("retrieve")) {
service.retrieve();
}
}
private boolean log(String msg) {
if (service != null) {
System.out.println("[Debug] 使用了" + msg + "方法");
return true;
} else {
System.out.println("[Error] 未绑定服务实现类");
return false;
}
}
}
public class LogProxyTest {
public static void main(String[] args) {
ServiceImpl serviceImpl = new ServiceImpl();
ServiceProxy serviceProxy = new ServiceProxy();
// 绑定前调用
serviceProxy.create();
serviceProxy.setService(serviceImpl);
// 绑定后调用
serviceProxy.create();
serviceProxy.delete();
serviceProxy.update();
serviceProxy.retrieve();
/*
[Error] 未绑定服务实现类
[Debug] 使用了create方法
增!
[Debug] 使用了delete方法
删
[Debug] 使用了update方法
改
[Debug] 使用了retrieve方法
查
*/
}
}
动态代理
代理类动态生成!
- 基于接口的动态代理
JDK动态代理 [我们一般使用这个] - 基于类的动态代理
cglib - 基于Java字节码实现动态代理
javasist
JDK动态代理 -> 基于接口!
需要使用的类
- InvocationHandler
是由代理实例调用处理程序实现的接口。
每个代理实例都有一个关联的调用处理程序。当在代理实例上调用方法时,方法调用将被编码并分派到其调用处理程序的invoke方法。

- Proxy
提供了创建动态代理类和实例的静态方法,它也是由这些方法创建的所有动态代理类的超类。
Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(), new Class<?>[] { Foo.class }, handler);
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 抽象主题
*/
interface Subject {
void method();
}
/**
* 真实主题
*/
class RealSubject implements Subject {
@Override
public void method() {
System.out.println("执行method中!");
}
}
/**
* 代理处理程序类
*/
class ProxyInvocationHandler implements InvocationHandler {
/**
* 代理的接口
* 这里传入的对象无论是什么都可以通过反射获取它的接口!!!
*/
private Object subject;
public void setSubject(Object subject) {
this.subject = subject;
}
/**
* 生成得到代理类
*
* @return 代理类
*/
public Object getProxy() {
return Proxy.newProxyInstance(this.getClass().getClassLoader(), subject.getClass().getInterfaces(), this);
}
/**
* 处理代理实例,并返回结果
*
* @param proxy 代理实例
* @param method 代理的方法
* @param args 代理的方法的参数
* @return 结果
* @throws Throwable 异常
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 动态代理的本质,就是利用反射机制实现
pre();
Object result = method.invoke(subject, args);
post();
return result;
}
private void pre() {
// 抽象方法执行前
System.out.println("method执行前!");
}
private void post() {
// 抽象方法执行后
System.out.println("method执行后!");
}
}
public class DynamicProxyTest {
public static void main(String[] args) {
// 真实主题
RealSubject realSubject = new RealSubject();
ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();
proxyInvocationHandler.setSubject(realSubject);
// 动态生成代理类
Subject proxy = (Subject) proxyInvocationHandler.getProxy();
// 使用代理类执行代理的接口的方法
proxy.method();
/*
* method执行前!
* 执行method中!
* method执行后!
*/
}
}
动态代理的好处
- 一个动态代理类代理的是一个接口,一般是对应的一类业务!
- 一个动态代理类可以代理多个类,只要是实现了同一个接口!
本文深入探讨了代理模式,包括静态代理和动态代理的原理、优势及实战示例,如租房中介和日志服务代理。重点介绍了JDK动态代理的实现,展示了如何通过InvocationHandler创建动态代理以实现业务代理和代码复用。
906

被折叠的 条评论
为什么被折叠?



