当前位置:首页 > 后端开发 > 正文

Java代理模式如何实现

在Java中设置代理模式可通过系统属性或Proxy类实现,系统属性方式设置全局代理,如 System.setProperty("http.proxyHost", "proxy.example.com");Proxy类则为单个连接指定代理,通过 ProxySelector动态管理,两种方法均支持HTTP/HTTPS/SOCKS协议,需注意代理验证和异常处理。

在Java中设置代理模式主要涉及两种实现方式:静态代理和动态代理(包括JDK动态代理和CGLIB动态代理),以下是详细实现指南:

静态代理(手动编写代理类)

原理:通过手动创建代理类,直接调用目标对象的方法,并在前后添加扩展逻辑。

// 1. 定义接口 interface UserService { void save(); } // 2. 实现目标类 class UserServiceImpl implements UserService { @Override public void save() { System.out.println("保存用户数据"); } } // 3. 创建代理类(关键) class UserServiceProxy implements UserService { private UserService target; // 目标对象 public UserServiceProxy(UserService target) { this.target = target; } @Override public void save() { System.out.println("【代理】操作前日志记录"); target.save(); // 调用目标方法 System.out.println("【代理】操作后资源清理"); } } // 4. 使用代理 public class StaticProxyDemo { public static void main(String[] args) { UserService target = new UserServiceImpl(); UserService proxy = new UserServiceProxy(target); proxy.save(); // 通过代理对象调用 } }

JDK动态代理(基于接口)

原理:利用java.lang.reflect.Proxy在运行时生成代理类,要求目标对象必须实现接口。

import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; // 1. 实现InvocationHandler class LogHandler implements InvocationHandler { private Object target; // 目标对象 public LogHandler(Object target) { this.target = target; } @Override 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; } } // 2. 生成代理对象 public class JdkProxyDemo { public static void main(String[] args) { UserService target = new UserServiceImpl(); // 创建代理实例 UserService proxy = (UserService) Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), // 获取接口数组 new LogHandler(target) ); proxy.save(); // 调用代理方法 } }

CGLIB动态代理(基于类继承)

原理:通过字节码技术生成目标类的子类作为代理,无需实现接口(需添加依赖)。

Java代理模式如何实现 第1张

  1. 添加Maven依赖

    Java代理模式如何实现 第2张

    Java代理模式如何实现 第3张

    <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.3.0</version> </dependency>
  2. 代码实现

    import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy;

class UserServiceInterceptor implements MethodInterceptor {

@Override

public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {

System.out.println(“【CGLIB代理】方法前增强”);

Object result = proxy.invokeSuper(obj, args); // 调用父类(目标类)方法

System.out.println(“【CGLIB代理】方法后增强”);

return result;

}

}

public class CglibProxyDemo {

public static void main(String[] args) {

Enhancer enhancer = new Enhancer();

enhancer.setSuperclass(UserServiceImpl.class); // 设置目标类为父类

enhancer.setCallback(new UserServiceInterceptor());

UserService proxy = (UserService) enhancer.create(); // 创建代理对象 proxy.save(); } --- ### **关键对比与选型建议** | 代理类型 | 优点 | 缺点 | 适用场景 | |----------------|-------------------------------|-------------------------------|------------------------------| | **静态代理** | 简单直观,无额外依赖 | 需手动编写代理类,维护成本高 | 简单方法增强或少量目标对象 | | **JDK动态代理**| 自动生成代理类,减少重复代码 | 目标类必须实现接口 | 基于接口的代理(如Spring AOP)| | **CGLIB代理** | 可代理无接口的类 | 无法代理final类/方法 | 代理普通类或第三方库 | --- ### **常见问题解决** 1. **JDK代理报`java.lang.ClassCastException`** **原因**:目标类未实现接口。 **方案**:改用CGLIB代理或为目标类添加接口。 2. **CGLIB代理final方法无效** **原因**:final方法无法被子类覆盖。 **方案**:避免代理final方法,或改用其他增强方式(如AspectJ)。 3. **性能优化** - JDK 8+ 对动态代理进行了性能优化,多数场景无需担心。 - 高并发场景优先使用JDK代理(CGLIB生成类耗时较长)。 --- ### **最佳实践** 1. **Spring框架中的选择** - 若目标类实现接口 → 默认用JDK代理 - 若目标类无接口 → 自动切换CGLIB - 强制使用CGLIB:在Spring Boot中配置`spring.aop.proxy-target-class=true` 2. **代理模式应用场景** - 权限控制(如拦截未登录请求) - 日志记录/性能监控 - 事务管理(如Spring声明式事务) - 远程方法调用(RPC) --- ### **引用说明** 1. JDK动态代理官方文档:[`java.lang.reflect.Proxy`](https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Proxy.html) 2. CGLIB开源项目地址:[GitHub - cglib/cglib](https://github.com/cglib/cglib) 3. 设计模式参考:《Head First Design Patterns》(O'Reilly) 4. Spring AOP原理:[Spring Framework Documentation](https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#aop) > 本文代码示例基于Java 11编写,依赖管理工具为Maven,实际使用时请确保环境兼容性,生产环境建议结合Spring AOP等成熟框架实现代理。

0