✅ 一、什么是代理(Proxy)?
通俗一点讲:
代理就是代表别人做事的中间人,你通过代理对象去调用目标对象的方法,中间可以加点料,比如:记录日志、权限验证、事务控制、性能监控等。
在代码里,这通常指:
创建一个“代理对象”,用它去间接调用“目标对象”,在调用过程中可以做增强处理。
📌 举个例子:
你去访问一个数据库服务:
UserService userService = new UserServiceImpl();
userService.addUser("张三");我们希望:
调用前打印日志
出异常时回滚事务
调用后记录调用时间
直接在 UserServiceImpl 里写这些会污染业务逻辑。于是我们可以用一个“代理”:
UserService proxy = new UserServiceProxy(userService);
proxy.addUser("张三");这个代理对象做的事情是:
public class UserServiceProxy implements UserService {
private UserService target;
public void addUser(String name) {
System.out.println("日志:准备添加用户");
try {
target.addUser(name);
System.out.println("日志:添加成功");
} catch (Exception e) {
System.out.println("日志:添加失败");
}
}
}✅ 二、为什么需要代理?
🌟 核心目的:在不修改原有代码的基础上,实现功能增强。
🧩 场景总结:
✅ 三、代理的常见方式
✅ 总结一句话:
代理是一种设计模式,目的是在不改变原始类的前提下,通过中间代理对象来“增强”方法执行的行为。
举例
✅ 1. 静态代理 — 自己写类封装目标对象
🌟 示例:用户服务加日志功能
// 接口
public interface UserService {
void addUser(String name);
}
// 实现类
public class UserServiceImpl implements UserService {
public void addUser(String name) {
System.out.println("添加用户:" + name);
}
}
// 静态代理类
public class UserServiceProxy implements UserService {
private UserService target;
public UserServiceProxy(UserService target) {
this.target = target;
}
public void addUser(String name) {
System.out.println("【日志】开始添加用户...");
target.addUser(name);
System.out.println("【日志】添加用户成功");
}
}✅ 使用:
UserService service = new UserServiceProxy(new UserServiceImpl());
service.addUser("张三");✅ 2. 动态代理(运行时生成类)
🌟 示例:JDK 动态代理
public class LogHandler implements InvocationHandler {
private Object target;
public LogHandler(Object target) {
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("【日志】方法调用前:" + method.getName());
Object result = method.invoke(target, args);
System.out.println("【日志】方法调用后");
return result;
}
}✅ 使用 JDK Proxy 创建代理:
UserService target = new UserServiceImpl();
UserService proxy = (UserService) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new LogHandler(target)
);
proxy.addUser("李四");✅ 3. 框架级代理(Spring AOP / MyBatis Mapper / Feign)
🌟 示例 1:Spring AOP
@Aspect
@Component
public class LogAspect {
@Before("execution(* com.example.service.*.*(..))")
public void beforeLog() {
System.out.println("【AOP日志】方法执行前");
}
}自动代理由 Spring 在后台完成(JDK 或 CGLIB):
@Service
public class UserService {
public void addUser(String name) {
System.out.println("添加用户:" + name);
}
}✅ 使用:
userService.addUser("王五"); // 实际是代理对象调用,触发 AOP🌟 示例 2:MyBatis Mapper
@Mapper
public interface UserMapper {
User selectById(int id);
}MyBatis 会用 JDK 动态代理创建这个接口的代理对象,自动生成 SQL 调用。
🌟 示例 3:Feign 远程调用(SpringCloud)
@FeignClient(name = "user-service")
public interface RemoteUserClient {
@GetMapping("/user/{id}")
User getUserById(@PathVariable Long id);
}Feign 在运行时为这个接口创建 代理对象,发起 HTTP 请求。