【Java】Reflection反射(代理模式)

发布于:2025-07-24 ⋅ 阅读:(24) ⋅ 点赞:(0)

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());
    }
    @Override
    public void request() {
        before();

        // 代理调用真实主题对象(目标对象)
        target.request();

        after();
    }

    private void after(){
        System.out.println("结束执行:" + LocalDateTime.now());
    }
}
// 目标类(真实主题角色)
class RealSubject implements Subject{
    @Override
    public 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());
    }

    @Override
    public 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{
    @Override
    public void select() {
        System.out.println("查询 select");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
    @Override
    public 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());
    }

    @Override
    public 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、总结

        代理模式是一种非常实用的设计模式,它通过引入代理对象来控制对目标对象的访问,为系统提供了更强的扩展性和灵活性。静态代理适用于简单场景,而动态代理则更适合复杂多变的场景。


网站公告

今日签到

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