【Java基础】7 动态代理

动态代理是代理模式的一种,代理模式指通过代理静默地解决一些业务无关的问题,比如远程、安全、事务、日志、资源关闭等,让开发者可以只关心业务。分为静态、动态代理:

静态代理:事先写好代理类

  • 实现简单,且不侵入原码

  • 缺点是每个业务类都需要写一个,非常不灵活,而且有冗余问题

    // 静态代理,给 UserService 添加日志处理
    public class UserServiceProxy implements UserService {
        // 被代理对象
        private UserService target;
        // 注入被代理对象
        public UserServiceProxy(UserService target) {
            this.target = target;
        }
        @Override
        public void select() {
            before();
            target.select();
            after();
        }
        // ......
    }
    

为解决这个问题,有了动态代理:

  • 优点是运行时自动生成代理对象

类能动态生成,依赖 JVM 的类加载机制,

加载阶段能通过运行时计算,生成代理类字节码加载到 JVM 中。

JVM 类加载过程分为:加载、验证、准备、解析、初始化。

其中加载又分为:

  • 通过类全限定名获取类二进制字节流,途径可以是运行时计算生成,这是动态代理的基础
  • 将字节流的静态存储转换为方法区的运行时数据结构
  • 生成类的 Class 对象

动态代理就是根据接口或目标对象,计算代理类的字节码,再加载到 JVM 中使用。

  • 缺点是生成代理对象、调用代理方法要额外花时间。

实现动态代理,有两种方式:

  • JDK 动态代理
    • 基于反射实现,依赖小,实现简单,只要实现 InvocationHandler 接口,重写 invoke() 即可
    • 缺点是只能代理接口,因为代理类本身继承了 Proxy 类。
// 调用处理器:给被代理类提供日志处理
public class MyLogHandler implements InvocationHandler {
    // 定义被代理对象
    private Object target;
    // 注入被代理对象
    public MyLogHandler(Object target){
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        // 调用 target 的 method 方法
        Object result = method.invoke(target,args); 
        after();
        return result;
    }
	// ......
}
public class Client {
    public static void main(String[] args) {
        // 被代理对象
        UserServiceImpl userServiceImpl = new UserServiceImpl();
        // 获取 ClassLoader
        ClassLoader classLoader = userServiceImpl.getClass().getClassLoader();
        // 获取所有接口的Class
        Class[] interfaces = userServiceImpl.getClass().getInterfaces();
        // 引入调用处理器
        MyLogHandler myLogHandler = new MyLogHandler(userServiceImpl);
        // 动态生成代理对象
        UserService proxy = (UserService) Proxy.newProxyInstance(classLoader,interfaces,myLogHandler);
        // 调用方法
        proxy.select();
    }
}
  • cglib 动态代理:
    • 创建业务类的子类作为代理类,不用实现接口,也不侵入源码,性能更高;
    • 但实现相对复杂,要实现 MethodInterceptor 接口,重写 intercept() ,通过 Enhancer 类的回调方法实现。

动态代理应用广泛,

常见比如:Spring AOP,Bean 有实现接口用 JDK 动态代理,没有则用 cglib 动态代理。

Java 动态代理详解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值