Java中动态代理如何实现,以及与静态代理的区别

在Java中 动态代理主要有两种实现方式

1.CGlib, 一个第三方代码生成类库, 运行时在内存中生成一个子类来实现动态代理, 通过字节码操作技术来实现动态代理, 在通过方法拦截机制对目标方法进行拦截或增强( 例如Servlet的filter ,分页插件等), 实现对接口的代理,配合AOP框架的使用

2.JDK动态代理: java.reflect中的Proxy和InvocationHandler接口

        如果实现了InvocationHandler这个接口定义了一个方法invoke(), 当通过代理对象调用接口方法时,实际上会触发到invoke()方法的调用。

        Proxy类提供了创建动态代理对象的静态方法 newProxyInstance()方法返回来一个实现了指定接口的代理对象,当这个代理对象的方法被调用时,会转发到对应InvocationHandler.invoke()方法中处理。

静态代理和动态代理的区别

        最大的区别就是静态代理在编译期间就会被确定的, 而动态代理则是在运行期间被确定的, 反射就是动态代理的其中一种实现方式

总结

        Java中 的动态代理, 基本是我们都会用到, 但其实感知不会那么明显, 主要的应用层面是SSM那一套比较熟悉, 例如AOP Servlter中的过滤器(MVC中的拦截器其实关系并不大,他更像是一种中间件),.mybatis中的分页插件, 或者说是我们针对分页参数的初始化操作, 事务,日志,权限,都离不开动态代理的身影子

JDK动态代理片段

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// 定义一个接口,我们的代理对象将实现此接口
interface MyService {
    void doSomething(String arg);
    int calculate(int a, int b);
}

// 目标对象,实现了MyService接口
class RealService implements MyService {
    @Override
    public void doSomething(String arg) {
        System.out.println("RealService: Doing something with " + arg);
    }

    @Override
    public int calculate(int a, int b) {
        return a + b;
    }
}

// 实现InvocationHandler接口,用于定义代理对象的行为
class LoggingHandler implements InvocationHandler {
    private final MyService target; // 被代理的目标对象

    public LoggingHandler(MyService target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Method '" + method.getName() + "' is being called.");

        // 在方法调用前添加日志或其他逻辑
        System.out.println("Arguments: " + Arrays.toString(args));

        // 调用目标对象的实际方法
        Object result = method.invoke(target, args);

        // 在方法调用后添加日志或其他逻辑
        System.out.println("Method returned: " + result);

        return result;
    }
}

public class DynamicProxyDemo {
    public static void main(String[] args) {
        // 创建实际的服务对象
        MyService realService = new RealService();

        // 创建InvocationHandler实例,传入目标对象
        InvocationHandler loggingHandler = new LoggingHandler(realService);

        // 使用Proxy.newProxyInstance创建代理对象,需要提供:
        // 1. 目标对象的类加载器
        // 2. 目标对象实现的所有接口
        // 3. 实现InvocationHandler接口的实例(定义代理行为)
        MyService proxy = (MyService) Proxy.newProxyInstance(
                MyService.class.getClassLoader(),
                new Class<?>[]{MyService.class},
                loggingHandler
        );

        // 现在可以像操作普通MyService对象一样操作代理对象
        proxy.doSomething("example argument");
        int sum = proxy.calculate(10, 20);
        System.out.println("Sum: " + sum);
    }
}

Cglib动态代理片段

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

// 目标类,无需实现接口
class TargetClass {
    public void doSomething(String arg) {
        System.out.println("TargetClass: Doing something with " + arg);
    }

    public int calculate(int a, int b) {
        return a + b;
    }
}

// 实现MethodInterceptor接口,用于定义代理对象的行为
class LoggingInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("Method '" + method.getName() + "' is being called on " + obj.getClass().getSimpleName());

        // 在方法调用前添加日志或其他逻辑
        System.out.println("Arguments: " + Arrays.toString(args));

        // 调用目标对象的实际方法
        Object result = proxy.invokeSuper(obj, args);

        // 在方法调用后添加日志或其他逻辑
        System.out.println("Method returned: " + result);

        return result;
    }
}

public class CGLibProxyDemo {
    public static void main(String[] args) {
        // 创建实际的目标对象
        TargetClass target = new TargetClass();

        // 创建Enhancer对象,指定要代理的类
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(TargetClass.class);

        // 设置回调方法,即代理逻辑
        enhancer.setCallback(new LoggingInterceptor());

        // 生成并返回代理对象
        TargetClass proxy = (TargetClass) enhancer.create();

        // 现在可以像操作普通TargetClass对象一样操作代理对象
        proxy.doSomething("example argument");
        int sum = proxy.calculate(10, 20);
        System.out.println("Sum: " + sum);
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值