代理模式通过统一接口让代理类与真实对象解耦,实现在不修改业务代码前提下织入日志、权限校验等横切逻辑;支持静态代理与jdk/cglib动态代理,可结合spring或工厂模式实现无侵入装配。

代理模式通过在目标对象前后插入额外逻辑,实现日志记录与权限校验等横切关注点,且无需修改原有业务代码——关键在于让代理类和真实对象实现同一接口,由代理统一接管调用。
定义统一接口,隔离业务与拦截逻辑
先抽象出核心业务行为的接口,比如 UserService:
- 所有具体服务(UserServiceImpl)和代理类(UserServiceProxy)都实现它
- 接口只暴露方法签名,不包含日志、鉴权等实现细节
- 调用方只依赖接口,完全感知不到代理的存在
编写代理类,在方法前后织入拦截逻辑
代理类持有一个真实对象引用,在调用前后插入日志与权限检查:
- 构造时传入真实服务实例,保持对原逻辑的完全复用
- 在 before() 中做权限校验:读取当前用户上下文、验证角色或 token,不通过直接抛异常
- 在 after() 或 finally 块中记录执行耗时、参数、返回值或异常信息
- 可结合注解(如 @RequireRole("ADMIN"))动态提取拦截规则,避免硬编码
用工厂或 IoC 容器自动装配代理,彻底无侵入
手动 new 代理类仍有侵入性,应交由框架管理:
- Spring 中开启 @EnableAspectJAutoProxy(proxyTargetClass = true),配合 @Aspect 切面更简洁;但若坚持代理模式,可用 @Bean 方法返回代理实例
- 自定义工厂类(如 UserServiceFactory)根据配置决定返回原始实现还是带拦截的代理
- 运行时通过 JDK 动态代理或 CGLIB 生成代理对象,对源码零修改,连编译期都不需要知道代理存在
区分静态代理与动态代理的适用场景
静态代理(手写代理类)适合少量、稳定接口,便于调试;动态代理更适合通用化拦截:
- JDK 动态代理要求目标类实现接口,适合大多数服务层场景
- CGLIB 代理可作用于无接口的类,但需注意 final 方法无法被拦截
- 无论哪种,日志与权限逻辑都封装在独立的 LogHandler 或 AuthInterceptor 中,便于复用和测试











