java实现动态代理所需的类或接口:

在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface)、另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的。

1.InvocationHandler

每一个动态代理类都必须要实现InvocationHandler接口,并且每个代理类的实列都关联了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的的invoker 方法来进行,我们来看看InvocationHandler接口的唯一一个方法invocker方法:

public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;

这个方法一共接收三个参数,那么这三个参数分别代表如下:

proxy:指代JDK动态生成的最终代理对象

method:指代的是我们所要调用真实对象的某个方法的method对象

args:指代的是调用真实对象某个方法时接受的参数。

2.Proxy

Proxy这个类的作用就是用来动态创建衣蛾代理对象的类,它提供了许多方法,

但是我们用的最多的就是newProxyInstance这个方法:

public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)throws IllegalArgumentException

这个方法的作用就是得到一个动态的代理对象,其接受三个参数,我们来看看这三个参数,

loader:一个ClassLoader对象,定义了由哪个ClassLoader来对生成的代理对象进行加载,

interfaces:一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,

如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了。

InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上,其实我们所说的DynamicProxy(动态代理类)是这样一种class:它是在运行时生成的class,如此一来,我们可以把该class的实列当做这些interface中的任何一个来用(可以强转为相应的接口类型)。当然,这个DynamicProxy其实就是一个Proxy,他不做作任何实质性的工作,在生成它的实列时你必须提供一个Handler,由它接管实际工作(即调用invocker方法)。

3.具体实例

//需要动态代理的接口
public interface Subject {
public void hello(String name);
public String bye();

}

//实现接口的实例

public class RealSubject implements Subject{

@Override
public void hello(String name) {
System.out.println("hello"+name);
}

@Override
public String bye() {
System.out.println("bye");
return "bye";
}

}

//每次生成动态代理对象时都需要指定一个实现了InvocationHandler接口对象
public class InvocationHandlerImpl implements InvocationHandler{
private Object subject;//这个就是我们要代理的真实对象,也就是真正执行业务逻辑的类

//通过构造方法传入这个被代理对象
public InvocationHandlerImpl(Object subject){
this.subject=subject;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result=null;
System.out.println("可以在调用实际方法前做一些事情");
System.out.println("当前调用的方法是" + method.getName());
// 当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
result = method.invoke(subject, args);// 需要指定被代理对象和传入参数
System.out.println(method.getName() + "方法的返回值是" + result);
System.out.println("可以在调用实际方法后做一些事情");
System.out.println("------------------------");
return result;// 返回method方法执行后的返回值
}

public Object getProxy(){
return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),subject.getClass().getInterfaces() , this);

}

//测试类:

public class Test {

public static void main(String[] args) {
//被代理的对象
Subject subject=new RealSubject();
InvocationHandlerImpl handler=new InvocationHandlerImpl(subject);
Subject proxy=(Subject) handler.getProxy();
System.out.println("动态代理对象的类型:"+subject.getClass().getName());
proxy.hello("tom");
proxy.bye();
}




}

//测试结果:

动态代理对象的类型:com.newtouch.invoker.RealSubject
可以在调用实际方法前做一些事情
当前调用的方法是hello
hellotom
hello方法的返回值是null
可以在调用实际方法后做一些事情
------------------------
可以在调用实际方法前做一些事情
当前调用的方法是bye
bye
bye方法的返回值是bye
可以在调用实际方法后做一些事情
------------------------

 

posted on 2018-05-17 13:43  蔡苗  阅读(90)  评论(0编辑  收藏  举报