代理模式是SpringAOP(面向切面编程)的底层原理
代理模式的分类
- 静态代理
- 动态代理
静态代理
角色分析:
抽象角色:一般使用抽象类或接口来解决
代理角色:代理真实角色,在代理真实角色后,一般会做一些附属操作
真实角色:被代理的角色
客户:访问代理对象的角色,可以理解为一个处理事务的线程,多为一次业务处理
以租房举例子进行理解
房东有房子要出租,将房源信息告诉中介,也就是让中介代理房东进行房屋租赁这件事。房东是真实角色(被代理的角色),中介是代理角色,房屋租赁这件事是抽象角色。
租房者是客户,相当于一次租房业务。
接下来上代码
抽象角色:房屋租赁这件事
package com.zbt.proxy.demo01;
/**
* @author
* @createAt 2025/1/12 20:58
*/
/**
* 租房 接口
*/
public interface Rent {
//出租事件 出租的是房子 对应着一个房东
void rent(Host host);
}
真实角色:房东 有两个属性 一个名字,一个房屋地址
package com.zbt.proxy.demo01;
/**
* @author
* @createAt 2025/1/12 20:59
*/
/**
* 房东
*/
public class Host implements Rent{
private String name;
private String address;
public Host() {
}
public Host(String name, String address) {
this.name = name;
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public void rent(Host host) {
System.out.println("我是房东:"+name+",我要出租房子,地址是:"+address);
}
}
代理角色:中介
package com.zbt.proxy.demo01;
/**
* @author
* @createAt 2025/1/12 21:01
*/
import java.util.ArrayList;
import java.util.List;
/**
* 中介 代理租房
*/
public class Proxy implements Rent{
//被代理的对象 对于中介来说就是一个房东
private Host;
public void setHost(Host host){
hostLs.add(host);
}
public Host getHost(){
return host;
}
public void rent(Host host) {
//中介知道房东要出租房子 也就是中介对于你来说 代理了这套房子的房东
host.rent(host);
//带你去看房子
seeHouse(host);
//你看中了房子 签合同
hetong();
//中介收了中介服务费
fare();
}
public void seeHouse(Host host){
System.out.println("中介带你看了在"+host.getAddress()+"的房子");
}
public void hetong(){
System.out.println("签租赁合同");
}
public void fare(){
System.out.println("收中介费");
}
}
客户:你 你要租房子 触发了一次租房业务流程(main方法)
package com.zbt.proxy.demo01;
/**
* @author
* @createAt 2025/1/12 21:00
*/
/**
* 租客要租房
*/
public class Client {
public static void main(String[] args) {
//被代理对象 -- 房东
Host host1 = new Host("房东1号","南京南街5-5-1号");
//代理对象 -- 中介
Proxy proxy;= new Proxy();
//房东在中介登记房子
proxy.setHostLs(host3);
//你要租房子 找到了中介 触发了租房流程
//中介给你介绍了一套房子
Host host = proxy.getHostLs(0);
//中介带你走租房流程 看房 签合同
proxy.rent(host);
}
}
静态代理模式的好处
- 可以使真实角色的“动作”更加纯粹:例如上面的例子,房东就只需要找中介登记一下房源,就可以等着房子出租出去了,不需要进行公共业务(带人看房,贴租房广告等)
- 公共业务交给代理角色来进行,进行过了业务的分工,
- 在公共业务需要进行扩展的时候方便集中管理,只需要改代理对象就可以了。
静态代理模式缺点
一个真实角色就会产生一个代理角色,代码量会增加,开发效率降低
模拟实际开发逻辑理解静态代理
实际开发经常用到用户信息的增删查改
我们通常的写法是:
package com.zbt.proxy.demo02;
/**
* 接口类
*/
public interface UserService {
void insert();
void delete();
void update();
void select();
}
package com.zbt.proxy.demo02;
/**
* @author
* @createAt 2025/1/12 22:01
*/
/**
* 实现类
*/
public class UserServiceImpl implements UserService{
public void insert() {
System.out.println("插入了一个用户");
}
public void delete() {
System.out.println("删除了一个用户");
}
public void update() {
System.out.println("修改了一个用户");
}
public void select() {
System.out.println("查询了一个用户");
}
}
package com.zbt.proxy.demo02;
/**
* 调用
* @author
* @createAt 2025/1/12 22:02
*/
public class Client {
public static void main(String[] args) {
UserServiceImpl userService = new UserServiceImpl();
userService.insert();
}
}
这样当然可以实现业务需求,但是当后期,如果在此基础上需要增加新的需求时,就得修改原有的业务逻辑代码,例如在调用每个方法时,增加一条日志记录,我们就需要去修改原来的UserServiceImpl 里面每一个方法,添加一条打印语句。如果需要进行的改较为复杂,那么修改原业务逻辑是致命的,此时我们将写法改为静态代理模式。
在原有基础上,增加一个代理类UserServiceProxy 代理UserServiceImpl
package com.zbt.proxy.demo02;
/**
* 代理类 代理UserServiceImpl 将UserServiceImpl 对象通过set方法传入 里面直接通过UserServiceImpl 对象调用对应方法,需要修改逻辑时,直接修改代理类,例如上面提到的增加一条调用日志打印
* @author
* @createAt 2025/1/12 22:03
*/
public class UserServiceProxy implements UserService{
private UserServiceImpl userService;
public UserServiceImpl getUserService() {
return userService;
}
public void setUserService(UserServiceImpl userService) {
this.userService = userService;
}
public void insert() {
log("insert");
userService.insert();
}
public void delete() {
log("delete");
userService.delete();
}
public void update() {
log("update");
userService.update();
}
public void select() {
log("select");
userService.select();
}
//日志打印方法
public void log(String msg){
System.out.println("调用了"+msg+"方法");
}
}
package com.zbt.proxy.demo02;
/**
* 调用
* @author
* @createAt 2025/1/12 22:02
*/
public class Client {
public static void main(String[] args) {
UserServiceImpl userService = new UserServiceImpl();
UserServiceProxy proxy = new UserServiceProxy();
proxy.setUserService(userService);
proxy.insert();
}
}