Spring AOP 代理模式解析

发布于:2025-06-22 ⋅ 阅读:(21) ⋅ 点赞:(0)

一、核心概念:代理模式就像房屋中介

想象你要租一套房子:

  • :租客(业务调用者)
  • 房东:房主(真实业务对象)
  • 中介:代理对象

传统方式(无代理)

租客 → 直接找房东
    ↓
房东处理所有事情:
   1. 带看房
   2. 签合同
   3. 收租金
   4. 处理维修

问题:房东被各种琐事淹没,无法专注核心业务(管理房屋)

二、代理模式解决方案

租客 → 联系中介(代理)
    ↓
中介处理辅助事务:
   1. 带看房 
   2. 签合同 
   3. 收租金 
   4. 处理维修 
    ↓
房东只做核心业务:确认租赁关系 

三、Spring AOP 中的两种代理

1. JDK 动态代理:基于接口的代理

场景:房东有明确的"租赁服务"接口

// 租赁服务接口
public interface RentalService {
    void signContract();
    void collectRent();
}

// 真实房东(实现接口)
public class Landlord implements RentalService {
    public void signContract() {
        System.out.println("房东签署合同");
    }
    
    public void collectRent() {
        System.out.println("房东收取租金");
    }
}

// 中介(代理)
public class AgencyProxy implements InvocationHandler {
    private Object target; // 持有房东引用
    
    public Object createProxy(Object target) {
        this.target = target;
        return Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            this
        );
    }
    
    public Object invoke(Object proxy, Method method, Object[] args) {
        // 前置增强:带看房
        System.out.println("中介带租客看房");
        
        // 调用房东方法
        Object result = method.invoke(target, args);
        
        // 后置增强:处理维修
        System.out.println("中介安排房屋维修");
        
        return result;
    }
}

// 租客使用
public class Renter {
    public static void main(String[] args) {
        Landlord realLandlord = new Landlord();
        RentalService proxy = (RentalService) new AgencyProxy().createProxy(realLandlord);
        
        proxy.signContract();
        proxy.collectRent();
    }
}

输出结果

中介带租客看房
房东签署合同
中介安排房屋维修

中介带租客看房
房东收取租金
中介安排房屋维修

2. CGLIB 代理:基于子类的代理

场景:房东没有实现接口

// 房东(无接口)
public class Landlord {
    public void signContract() {
        System.out.println("房东签署合同");
    }
    
    public void collectRent() {
        System.out.println("房东收取租金");
    }
}

// 中介(代理)
public class AgencyInterceptor implements MethodInterceptor {
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) {
        // 前置增强
        System.out.println("中介带租客看房");
        
        // 调用房东方法
        Object result = proxy.invokeSuper(obj, args);
        
        // 后置增强
        System.out.println("中介安排房屋维修");
        
        return result;
    }
}

// 租客使用
public class Renter {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(Landlord.class);
        enhancer.setCallback(new AgencyInterceptor());
        
        Landlord proxy = (Landlord) enhancer.create();
        proxy.signContract();
        proxy.collectRent();
    }
}

输出结果:与JDK代理相同

四、Spring AOP 如何选择代理方式?

 

实际场景对比

代理类型 比喻场景 优势 限制
JDK动态代理 房东有租赁资质证书(接口) 无需额外依赖 只能代理接口方法
CGLIB代理 房东是个人房东(无证书) 可代理普通类 无法代理final方法

五、Spring AOP 代理工作流程 

 

六、为什么需要代理模式?

1. 解决核心问题:关注点分离

关注点 房东职责 中介职责
核心业务 确认租赁关系 -
辅助事务 - 带看房/签合同/维修
客户接触 - 直接面对租客

2. 实际开发中的对应关系

房屋租赁 Spring AOP 技术实现
房东 服务类(如UserService) @Service
中介 代理对象 Spring容器创建
带看房 前置通知 @Before
签合同 核心方法 业务逻辑
处理维修 后置通知 @After
租赁接口 服务接口 UserService接口

 

七、实际代码示例

1. 定义切面(中介服务)

@Aspect
@Component
public class AgencyServices {
    
    // 带看房服务(前置通知)
    @Before("execution(* com.example.service.*.*(..))")
    public void showHouse() {
        System.out.println("中介带租客看房");
    }
    
    // 处理维修(后置通知)
    @After("execution(* com.example.service.*.*(..))")
    public void handleMaintenance() {
        System.out.println("中介安排房屋维修");
    }
}

2. 业务服务(房东)

@RestController
public class RentalController {
    @Autowired
    private LandlordService landlordService;
    
    @PostMapping("/sign")
    public String signContract() {
        landlordService.signContract();
        return "签约成功";
    }
}

3. 客户端调用

@Service
public class LandlordService {
    public void signContract() {
        System.out.println("房东签署合同");
    }
    
    public void collectRent() {
        System.out.println("房东收取租金");
    }
}

4. 执行结果

访问 POST /sign
输出:
中介带租客看房
房东签署合同
中介安排房屋维修

 

八、代理模式的优势总结

  1. 职责清晰

    • 房东专注核心业务
    • 中介处理辅助事务
  2. 扩展灵活

    • 新增服务只需添加新切面
    • 不影响核心业务逻辑
  3. 解耦彻底

    • 房东不知道中介存在
    • 中介不知道房东具体实现
  4. 保护目标对象

    • 租客不直接接触房东
    • 中介控制访问流程

九、Spring AOP 代理的本质

通过代理对象包裹目标对象,在不修改原始代码的前提下,在方法执行前后插入增强逻辑,实现功能扩展。


网站公告

今日签到

点亮在社区的每一天
去签到