在Java的java.lang.reflect包下提供一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口可以生成jdk动态代理类或动态代理对象。
Proxy是所有动态代理类的父类,它提供了两个静态方法来创建动态代理类和动态代理对象,如下:
//获得代理对象的Class对象
static
Class<?>
getProxyClass(
ClassLoader loader,
Class<?>... interfaces)
//获得一个完整的代理对象
static
Object
newProxyInstance(
ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
getProxyClass返回代理类的 java.lang.Class 对象,并向其提供类加载器和接口数组。newProxyInstance返回一个指定接口的代理类实例,该接口可以将方法调用转发到指定的调用处理程序,执行代理对象的每个方法时都会被替换执行InvocationHandler对象的Invoke方法。实际上,即使采用第一种方式获取了一个动态代理类之后,当程序需要通过该代理类来创建对象时一样需要传入一个InvocationHandler对象。也就是说,系统生成的每个代理对象都有一个与之关联的InvocationHandler对象。
从上面的两个方法的参数可以看出,只有给我一个(或多个)接口,我们就可以生成实现了这个(或多个)接口的代理类和代理对象。
2. 两种方式生成代理对象
下面我们就用上面提到两种方式,分别来生成一个接口(Person)的代理对象。
2.1 接口Person
package com.tgb.reflect;
/**
* 目标接口
*/
public interface Person {
public void walk();
public void sayHello();
}
2.2 构造一个InvocationHandler类
package com.tgb.reflect;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
//这个类中存放的是真正的业务逻辑
public class MyInvocationHandler implements InvocationHandler {
/**
* proxy :代表动态代理对象而不是被代理对象; method:代表正在执行的方法 ;args :代表执行代理对象方法时传入的实参
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("正在执行方法:" + method.getName());
//注意传入的target不是动态代理对象proxy,而是被代理对象,如果要同时执行原对象中的业务逻辑就需要在这里注入被代理对象
method.invoke(target,args);
return null;
}
}
2.3 方式一:利用getProxyClass生成代理对象
package com.tgb.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
/**
* 利用getProxyClass生成代理对象
*
* @author wangzhipeng
*
*/
public class TestReflectProxy {
@SuppressWarnings("unchecked")
public static void main(String[] args) throws Exception {
// 1、创建一个InvocationHandler对象
InvocationHandler myInvocationHandler = new MyInvocationHandler();
// 2、创建Person接口的一个代理类(获取代理类的字节码)
Class proxyClass = Proxy.getProxyClass(Person.class.getClassLoader(), new Class[] { Person.class });
// 3、根据代理类的字节码拿到它的参数为InvocationHandler类型的构造器
Constructor constructor = proxyClass.getConstructor(new Class[] { InvocationHandler.class });
// 4、根据构造器创建代理对象
Person person = (Person) constructor.newInstance(myInvocationHandler);
// 5、调用代理对象的方法
person.walk();
person.sayHello();
/**
* 输出结果如下:
*
* 正在执行方法:walk 该方法调用无实参!
*
* 正在执行方法:sayHello 该方法调用无实参!
*/
}
}
2.4 方式二:利用newProxyInstance生成代理对象
package com.tgb.reflect;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
/**
* 利用newProxyInstance生成代理对象
*
* @author wangzhipeng
*
*/
public class TestReflectProxy2 {
public static void main(String[] args) {
// 1、创建一个InvocationHandler对象
InvocationHandler myInvocationHandler = new MyInvocationHandler();
// 2、利用Proxy类的静态方法newProxyInstance直接生成Person接口的代理对象
Person person = (Person) Proxy.newProxyInstance(Person.class.getClassLoader(), new Class[] { Person.class }, myInvocationHandler);
// 3、调用代理对象的方法
person.walk();
person.sayHello();
/**
* 输出结果如下:
*
* 正在执行方法:walk 该方法调用无实参!
*
* 正在执行方法:sayHello 该方法调用无实参!
*/
}
}