在java的java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过这个类和这个接口可以生成动态代理类和动态代理对象。
每一个动态代理类都必须要实现InvocationHandler接口,并且每个代理类的实例都关联到了一个handler,当通过代理对象调用一个方法的时候,这个方法的调用就会被转发给由InvocationHandler接口的invoke方法进行调用,
invoke方法的介绍:
Object invoke(Object proxy,Method method,Object[] args) throws Throwable
proxy:表示我们代理的真实对象
method:表示我们代理的真实对象的某个方法
args:表示调用真实对象某个方法时接受的参数
Proxy类的作用是动态的创建一个代理对象的类,我们使用的最多的是newProxyInstance方法。
newProxyInstance()方法的作用是创建一个动态的代理对象,它接受三个参数,分别是:
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) throws IllegalArgumentException
其中:
loader:classLoader对象,表示定义使用哪个ClassLoader对生成的代理对象进行加载。
interfaces:表示给代理对象提供一组接口,如果提供一组接口给代理对象,代理对象就宣称实现了该接口,这样我们就能调用这组接口中的方法。
h:表示代理对象在调用方法的时候会关联到哪一个InvocationHandler对象上。
下面举一个例子来说明一下:
首先定义一个接口Subject
public interface Subject{
public void rent();
public void hello(String str);
}
定义一个类实现这个接口,这个类就是我们的真实对象
public class RealSubject implements Subject{
@Override
public void rent(){
System.out.println("I want to rent my house");
}
@Override
public void hello(String str){
System.out.println("hello: " + str );
}
}
定义一个动态代理类,每个动态代理类都必须实现InvocationHandler这个接口。
public class DynamicProxy implements InvocationHandler{
private Object subject; // 需要代理的真实对象
public DynamicProxy(Object object){
this.subject = subject;
}
@Override
public Object invoke(Object object,Method method,Object[] args) throws Throwable{
System.out.println("before rent house");
System.out.println("Method: "+ method);
method.invoke(subject,args); //当代理对象调用真实对象的方法时,会自动跳转到代理对象关联的handler对象的invoke方法来进行调用。
System.out.println("after rent house");
return null;
}
}
最后是Client类:
public class Client{
public static void main(String[] args){
Subject realSubject = new RealSubject();
InvocationHandler handler = new DynamicProxy(realSubject);
Subject subject = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(),realSubject.getClass().getInterfaces(),handler);
System.out.println(subject.getClass().getName());
subject.rent();
subject.hello("world");
}
}
输出为:
$Proxy0
before rent house
Method:public abstract void com.xiaoluo.dynamicproxy.Subject.rent()
I want to rent my house
after rent house
before rent house
Method:public abstract void com.xiaoluo.dynamicproxy.Subject.hello(java.lang.String)
hello: world
after rent house
通过Proxy.newProxyInstance创建的代理对象是在JVM运行时就动态生成的一个对象,它并不是InvocationHandler类型,也不是接口类型,而是运行时动态生成的一个对象,并且命名方式是以$开头,proxy在中间,最后一个数字表示对象的标号。
项目中应用动态代理的例子:
是不同模块之间通信。
一个模块中创建远程接口,生成接口的代理对象,另一个模块调用该模块的方法,会被转发到实现的invocationHandler类的invoke()方法上,再invoke()方法上使用http进行调用。
网友评论