动态代理是指代理类对象在程序运行时由 JVM 根据反射机制动态生成的。动态代理不需要定义代理类的.java 源文件。动态代理其实就是 jdk 运行期间,动态创建 class 字节码并加载到 JVM。动态代理的实现方式常用的有两种:使用 JDK 动态代理和 CGLIB 动态代理。
-
- JDK动态代理
JDK动态代理是基于 Java 的反射机制实现的。使用 JDK中接口和类实现代理对象的动态创建。JDK的动态代理要求目标对象必须实现接口,而代理对象不必实现业务接口,这是 java 设计上的要求。从 jdk1.3 以来,java 语言通过 java.lang.reflect 包提供三个类和接口支持代理模式,它们分别Proxy, Method和 InvocationHandler。
-
-
- InvocationHandler接口
-
InvocationHandler 接口叫做调用处理器,负责完成调用目标方法,并增强功能。通过代理对象执行目标接口中的方法 , 会把方法的调用分派给调用处理器(InvocationHandler)的实现类,执行实现类中的 invoke()方法,我们需要把功能代理写在 invoke()方法中 。此接口中只有一个方法。
在 invoke 方法中可以截取对目标方法的调用。在这里进行功能增强。Java 的动态代理是建立在反射机制之上的。实现了 InvocationHandler 接口的类用于加强目标类的主业务逻辑。这个接口中有一个方法 invoke(),具体加强的代码逻辑就是定义在该方法中的。通过代理对象执行接口中的方法时,会自动调用 invoke()方法。
invoke()方法的介绍如下:
public Object invoke ( Object proxy, Method method, Object[] args)
proxy:代表生成的代理对象
method:代表目标方法
args:代表目标方法的参数
第一个参数 proxy 是 jdk 在运行时赋值的,在方法中直接使用,第二个参数后面介绍,
第三个参数是方法执行的参数, 这三个参数都是 jdk 运行时赋值的,无需程序员给出。
-
-
- Method 类
-
invoke()方法的第二个参数为 Method 类对象,该类有一个方法也叫 invoke(),可以调用目标方法。这两个 invoke()方法,虽然同名,但无关。
public Object invoke ( Object obj, Object... args)
obj:表示目标对象
args:表示目标方法参数,就是其上一层 invoke 方法的第三个参数
该方法的作用是:调用执行 obj 对象所属类的方法,这个方法由其调用者 Method 对象确定。在代码中,一般的写法为
method.invoke(target, args);
其中,method 为上一层 invoke 方法的第二个参数。这样,即可调用了目标类的目标方法。
-
-
- Proxy类
-
通过JDK的java.lang.reflect.Proxy类实现动态代理,会使用其静态方法newProxyInstance(),依据目标对象、业务接口及调用处理器三者,自动生成一个动态代理对象。
public static newProxyInstance ( ClassLoader loader, Class<?>[] interfaces,
InvocationHandler handler)
loader:目标类的类加载器,通过目标对象的反射可获取
interfaces:目标类实现的接口数组,通过目标对象的反射可获取
handler:调用处理器。
-
-
- 实现步骤
-
- 代理对象不需要实现接口
- 代理对象的生成是利用JDKAPI中的Proxy类, 动态的在内存中构建代理对象
- 代码实现结构
- ProxyFactory.java代理实例生成工厂
public class ProxyFactory {
//任何的代理对象,都要清楚目标对象,在此得设置一个目标对象,
private IService superStar;
//传入目标对象
public ProxyFactory(IService superStar){
this.superStar=superStar;
}
//给目标对象生成代理实例
public Object getProxyInstance(){
return Proxy.newProxyInstance(
//指定当前目标对象,使用类加载器获得
superStar.getClass().getClassLoader(),
//获得目标对象实现的所有接口
superStar.getClass().getInterfaces(),
//处理代理实例上的方法并返回调用结果
new InvocationHandler(){
@Override
public Object invoke(
//代理对象的实例
Object proxy,
//代理的目标对象的实现方法
Method method,
//代理的目标对象实现方法的参数
Object[] args) throws Throwable {
System.out.println("预定场地..........");
//目标对象执行自己的方法
Object returnValue=method.invoke(superStar, args);
System.out.println("结帐走人.........");
return returnValue;
} });}}
- 测试类
@Test
public void testDynamicProxy(){
//先创建目标对象
IService superStar=new SuperStar();
//创建代理对象
IService agent=(IService) new ProxyFactory(superStar).getProxyInstance();
agent.sing();
}
注意:JDK动态代理中,代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能用JDK动态代理。