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
可以在调用实际方法后做一些事情
------------------------