Java中的《动态代理》

69 阅读3分钟

Java中什么是动态代理

动态代理可以理解为一种代理模式,它运行时就会对对象进行动态代理,将所有方法的调用都用到目标对象上。同时动态代理一般使用Java的反射机制来实现的。

Java中的动态代理需要两个关键的组件:

1.接口类:接口类定义目标对象和代理对象的共同行为。

2.代理类:代理类是动态生成的,继承Proxy类并实现了目标接口。

当调用代理对象的方法时,实际上是在调用父类的Proxy的invoke()方法,然后由invoke()方法再通过反射机制将方法调用转发到目标对象上。

使用动态代理示例代码:

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

// 定义接口
interface UserService {
    void addUser(String name);
}

// 实现目标对象
class UserServiceImpl implements UserService {
    public void addUser(String name) {
        System.out.println("Add user: " + name);
    }
}

// 实现InvocationHandler接口创建代理类
class UserServiceProxy implements InvocationHandler {
    private Object target;

    public Object bind(Object target) {
        this.target = target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), this);
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 在调用方法之前的操作
        System.out.println("Before method: " + method.getName());

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

        // 在调用方法之后的操作
        System.out.println("After method: " + method.getName());

        return result;
    }
}

public class DynamicProxyExample {
    public static void main(String[] args) {
        // 创建目标对象
        UserService userService = new UserServiceImpl();

        // 创建代理对象
        UserServiceProxy proxy = new UserServiceProxy();
        UserService proxyInstance = (UserService) proxy.bind(userService);

        // 调用代理对象的方法
        proxyInstance.addUser("Alice");
    }
}

通过定义接口UserService和实现类UserServiceImpl来表示目标对象。然后使用UserServiceProxy类实现InvocationHandler接口,并通过Proxy.newProxyInstance()方法动态创建代理对象。在invoke()方法中,可以添加额外的操作,如在目标方法调用之前和之后记录日志。

输出结果如下:

Before method: addUser
Add user: Alice
After method: addUser

调用代理对象的addUser()方法时,实际执行了目标对象的addUser()方法,并且在方法调用之前和之后添加了额外的操作。

动态代理的使用场景

日志记录:通过动态代理,可以在不修改源码的情况下,在方法调用前后记录日志,实现记录日志的功能。

性能监控: 可以使用动态代理来监控方法的执行时间,统计时间,然后对代码进行优化。

事务管理: 在方法调用前开启事务,在方法调用后提交或者回滚事务,实现事务管理。

AOP(面向切面编程): 动态代理是实现AOP的一种常用方式,通过动态代理可以在不修改原始类的前提下,将额外的逻辑(如日志、事务、安全等等)横切到目标方法调用中。

安全控制: 通过动态代理,可以在方法调用进行权限检查,验证用户身份和权限,从而实现安全控制。

远程方法的调用(RPC): 动态代理可以用于实现远程方法调用,通过网络将方法调用的请求发送到远程服务器上,获取执行结果返回给客户端。

动态代理的优缺点:

优点:

1.对于代码来说,具有更低的耦合性,可以对目标对象进行扩展或者增强,避免了直接修改目标对象的代码。

2.灵活性高、通用性高,可以适用于各种不同的目标对象,不需要对目标对象编写独立的代理类

3.方便后期需求改变时对代码的修改,不需要动目标对象的代码。

缺点: 1.会有一定的性能损耗,但是又可以忽略不计,影响不大

2.需要目标对象有实现接口,没有接口就无法代理目标对象中非接口的方法。

以上皆为本人对动态代理的理解,如有疏漏或错误,欢迎在评论区补充,谢谢!