Bootstrap

SpringAOP前置——代理模式

代理模式是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();
    }
}


;