Java的动态代理主要基于以下原理:
- 代理模式:
- 代理模式是一种设计模式,它通过创建一个代理对象来控制对真实对象的访问。
- 代理对象可以在调用真实对象之前或之后增加额外的逻辑,如权限验证、记录日志等。
- 运行时动态生成代理类:
- Java的动态代理是在运行时动态生成代理类的技术。
- 这个动态生成的代理类会继承被代理类的接口(注意:这里是指基于接口的动态代理,另一种基于类的动态代理如CGLib则不同),并重写被代理类接口中的方法。
- InvocationHandler接口和Proxy类:
- Java的动态代理主要使用
java.lang.reflect.Proxy
类和java.lang.reflect.InvocationHandler
接口来实现。 InvocationHandler
接口是一个回调接口,包含一个invoke()
方法,用来处理代理对象的方法调用。Proxy
类则是用来动态生成代理类的工具类,它可以根据被代理类的接口生成一个代理类,代理类实现了被代理类的接口,并且在代理类中调用了InvocationHandler
的invoke()
方法。
- Java的动态代理主要使用
- 实现步骤:
- 定义一个被代理类和一个实现
InvocationHandler
接口的代理类。 - 在代理类中实现
invoke()
方法,该方法用于处理代理对象的方法调用。在invoke()
方法中,根据传递进来的方法名和参数,调用被代理类中相应的方法,并在需要的时候进行拦截和增强操作。 - 利用
Proxy
类的newProxyInstance()
方法,动态生成一个代理对象。这个方法需要传递三个参数:被代理类的类加载器、被代理类的接口数组和代理类(即实现了InvocationHandler
接口的类)。 - 最后,通过代理对象调用相应的方法,代理对象会将方法名和参数传递给
InvocationHandler
,由InvocationHandler
进行处理。
- 定义一个被代理类和一个实现
- 基于接口的动态代理:
- Java的动态代理主要是基于接口的代理技术,因此被代理类必须要实现接口。
- 如果被代理类没有实现接口,可以使用如CGLib等其他代理技术。
- 优点:
- 动态生成代理类,无需手动编写代理类代码,减少了代码量和维护难度。
- 可以在不修改原有代码的基础上,扩展对象的行为。
-
动态代理和静态代理在Java中的主要区别可以归纳如下:
1. 代理方式
- 静态代理:
- 静态代理通常只代理一个类。
- 代理类和委托类有共同的父类或父接口,代理角色固定。
- 在应用程序执行前就得到目标角色。
- 动态代理:
- 动态代理是代理一个接口下的多个实现类。
- 代理的目标对象不固定,只有在运行时才知道要代理什么。
- 动态代理类的字节码在程序运行时,由Java反射机制动态产生。
-
2. 实现方式
- 静态代理:
- 需要为每个需要代理的类手动编写代理类。
- 代理类负责请求的预处理、过滤、将请求分派给委托类处理、以及委托类执行完请求后的后续处理。
- 动态代理:
- 通过实现JDK里的
InvocationHandler
接口的invoke
方法,不需要手动编写代理类的源代码。 - 使用
Proxy
类的newProxyInstance
方法动态生成代理对象。 - 代理的是接口,即业务类必须要实现接口。
- 另外,还有CGLIB这样的动态代理方式,它代理的是类,通过派生的子类来实现代理。
- 通过实现JDK里的
-
3. 灵活性
- 静态代理:
- 灵活性较低,因为需要为每个类编写代理类。
- 代理的角色固定,适用于少量且固定的代理需求。
- 动态代理:
- 灵活性较高,可以在运行时动态地为目标对象创建代理对象。
- 适用于大量且动态变化的代理需求。
-
4. 应用场景
- 静态代理:
- 通常应用于电子商务、媒体矩阵、邮件保护等场景。
- 在网络安全方面,可以实现对目标服务器请求进行记录和过滤。
- 动态代理:
- 在不修改原始类的情况下,对原始类的方法进行拦截或增强。
- AOP(面向切面编程)就是基于动态代理实现的,如Spring框架、Hibernate框架等都使用了动态代理。
-
5. 优缺点
- 静态代理:
- 优点:简单直接,易于理解。
- 缺点:代理类数量多,可能引起“类爆炸”;灵活性低,不易于扩展。
- 动态代理:
- 优点:灵活性强,可动态生成代理类;代码量小,易于维护。
- 缺点:由于使用了反射机制,可能带来一定的性能开销。