【Java】Reflection反射(代理模式)
1、代理模式
给某个对象提供一个代理对象,并由代理对象来控制其对真实对象的访问。
Subject(抽象主题角色):定义代理类和真实主题的公告对外方法,通常设计为接口。
RealSubject(真实主题角色):定义真正的业务实现类。
Proxy(代理主题角色):用来代理和封装真实主题。
2、静态代理
代理类在编译时就已经确定,每个目标类都需要对应一个代理类,代码结构相对固定。
public class Client {public static void main(String[] args) {Subject subject = new Proxy();subject.request();}
}
// 代理类(代理主题角色)
class Proxy implements Subject{private Subject target;public Proxy(){target = new RealSubject();}private void before(){System.out.println("开始执行:" + LocalDateTime.now());}@Overridepublic void request() {before();// 代理调用真实主题对象(目标对象)target.request();after();}private void after(){System.out.println("结束执行:" + LocalDateTime.now());}
}
// 目标类(真实主题角色)
class RealSubject implements Subject{@Overridepublic void request() {System.out.println("真实方法被调用,正在执行!!!");try {// 模拟耗时操作Thread.sleep(2000);} catch (InterruptedException e) {throw new RuntimeException(e);}}
}
// Subject(抽象主题角色)
interface Subject {void request();
}// 结果:
开始执行:2025-07-23T17:58:37.625
真实方法被调用,正在执行!!!
结束执行:2025-07-23T17:58:39.643
3、动态代理
代理类在运行时动态生成,无需手动编写每个代理类,灵活性更高。Java 中常用的动态代理方式有 JDK 动态代理和 CGLIB 代理。
1、JDK代理
JDK 动态代理主要涉及两个类:java.lang.reflect.Proxy 和 java.lang.reflect.InvocationHandler 我们通过编写一个调用逻辑处理器 LogHandler 类案例来提供日志增强功能,并实现 InvocationHandler 接口;在 LogHandler 中维护一个目标对象,这个对象是被代理的对象(真实主题角色);在 invoke () 方法中编写方法调用的逻辑处理。
public class Client01 {public static void main(String[] args) {// 真实主题(目标对象)UserServiceImpl userServiceTarget = new UserServiceImpl();// 获取目标对象的类加载器ClassLoader classLoader = userServiceTarget.getClass().getClassLoader();// 获取目标对象的接口列表Class[] interfaces = userServiceTarget.getClass().getInterfaces();// 日志组件(添加额外操作组件相当于Proxy)LogHandler logHandler = new LogHandler(userServiceTarget);// 创建一个代理对象// 参数1:类加载器(目标对象和代理对象的类加载器需要保持一致)// 参数2:抽象主题接口// 参数3:InvocationHandler接口实现类对象(附加行为代码的定义)IUserService userService = (IUserService) Proxy.newProxyInstance(classLoader,interfaces,logHandler);// 调用业务方法userService.select();}
}class LogHandler implements InvocationHandler {private Object target;public LogHandler(Object target){this.target = target;}private void before(){System.out.println("开始执行:" + LocalDateTime.now());}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {before();Object returnVale = method.invoke(target,args);after();return returnVale;}private void after(){System.out.println("结束执行:" + LocalDateTime.now());}}class UserServiceImpl implements IUserService{@Overridepublic void select() {System.out.println("查询 select");try {Thread.sleep(2000);} catch (InterruptedException e) {throw new RuntimeException(e);}}@Overridepublic void update() {System.out.println("更新 update");}
}interface IUserService {void select();void update();
}// 结果:
开始执行:2025-07-23T18:38:02.468
查询 select
结束执行:2025-07-23T18:38:04.470
动态代理我们不需要知道自己创建代理类,而是通过方法动态的创建代理对象,从而可以使 其运用更加灵活。
2、CGLIB 代理
CGLIB是一个强大的、高性能的代码生成库,它允许运行时扩展或者修改类的接口。
1、无需接口:可以代理灭有实现接口的类。
2、性能较高:CGLIB使用字节码生成技术,生成代理类的效率要高于Java反射。
3、方法拦截:通过实现MethodInterceptor接口,可以拦截需要增强的目标类的方法。
public class Client02 {public static void main(String[] args) {Enhancer enhancer = new Enhancer();// 设置父类(目标类): cglib基于继承的方式,创建Proxy代理对象enhancer.setSuperclass(UserService.class);// 设置拦截器enhancer.setCallback(new LogHandlerCg());// 创建代理对象UserService userService = (UserService) enhancer.create();// 通过代理对象,调用目标方法userService.select();}
}class LogHandlerCg implements MethodInterceptor{private void before(){System.out.println("开始执行:" + LocalDateTime.now());}private void after(){System.out.println("结束执行:" + LocalDateTime.now());}@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {before();Object returnValue = methodProxy.invokeSuper(o,objects);after();return returnValue;}
}class UserService{public void select(){System.out.println("查询 select");}public void update(){System.out.println("更新 update");}
}
4、总结
代理模式是一种非常实用的设计模式,它通过引入代理对象来控制对目标对象的访问,为系统提供了更强的扩展性和灵活性。静态代理适用于简单场景,而动态代理则更适合复杂多变的场景。