一、在java动态代理机制中涉及的角色
1、委托类和委托对象:也可以称为业务类、真正类和业务对象、真正对象,比如;UserServiceImpl.java
2、程序处理类、目标类(或代理类):实现InvocationHandler接口的类,实现invoke()方法,比如:LogHandler.java
处理程序对象、目标对象(或代理对象):invocation handler,由程序处理类、目标类(或代理类)创建的对象,比如:new LogHandler(),它是invoke()方法的实际调用者;
3、动态代理类:proxy classess,由Proxy.getProxyClass(loader, interfaces)获取的类,所有动态代理类的基类都是Proxy类
动态代理对象:proxy instance,由Proxy.newProxyInstance()获取的实例对象,该动态代理对象与代理对象不同,它的类型与委托对象类型相同,而代理对象的类型是InvocationHandler类型。
动态代理对象将会调用委托类的业务方法,比如:saveUser(),触发调用代理对象invoke()方法,其内部再调用委托类的业务方法.
注:此处强行区分代理对象和动态代理对象,因为它们的职责不同,也为了更好的理解动态代理的逻辑、机制。
二、java的动态代理机制中的核心接口和类
java的动态代理机制中的核心接口和类,分别是 InvocationHandler(Interface)、 Proxy(Class)。首先我们先来看看java的API帮助文档是怎么样对这个接口和类进行描述的:
1、InvocationHandler:
/**
* InvocationHandler is the interface implemented by
* the invocation handler of a proxy instance.
*
* Each proxy instance has an associated invocation handler.
*
* When a method is invoked on a proxy instance, the method
* invocation is encoded and dispatched to the invoke
* method of its invocation handler.
*
*/
InvocationHandler是一个接口,它会被动态代理对象的调用处理程序类(代理类)实现。
即每一个代理类都必须要实现InvocationHandler这个接口,并且每个动态代理对象都会关联到这个代理类的对象:handler,当我们通过动态代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。我们来看看InvocationHandler这个接口的唯一一个方法 invoke 方法:
Object invoke(Object proxy, Method method, Object[] args) throws Throwable
/**
*
*proxy:动态代理对象,即由Proxy.newProxyInstance()创建的对象
*
*method:委托对象的方法的Method对象,即真正方法的Method对象
*
*args:调用委托对象(真实对象)方法时传递的参数
*/
2、Proxy类:
/**
* Proxy provides static methods for creating dynamic proxy
* classes and instances, and it is also the superclass of all
* dynamic proxy classes created by those methods.
*/
Proxy类的作用就是提供静态的方法创建动态代理类和动态代理对象,方法分别为:
public static Class<?> getProxyClass(ClassLoader loader,Class<?>... interfaces)
throws IllegalArgumentException
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
throws IllegalArgumentException
/**
*
*loader:一个ClassLoader对象,定义动态代理类使用的类加载器
*
*interfaces:一个Interface对象的数组,定义动态代理类所要实现的接口列表
*
*h:一个InvocationHandler对象,表示动态代理对象在调用方法的时候,所关联的代理对象,也就是实现了InvokeHandler接口的实现类对象
*/
3、补充:
动态代理机制中,ClassLoader类作为类的加载器,也是核心的一部分。
三、动态代理实例
按照下面的一个小故事作为需求,通过动态代理实现:
有一个人,他叫王守财,做生意遇到了麻烦事,他想把对方弄死(有点暴力),但是他需要周密的部署和工具,所以他找了当地黑社会的头头,外号大B哥,大B哥说,这个好办,应下了此事。大B哥作为老大,具体动手都是由手下的马仔,大B哥只是负责组织,在幕后掌控一切。
依据上面的故事情景,对应动态代理的角色,如下:
委托对象:王守财
目标对象、代理对象:大B哥
动态代理对象:任意一个马仔
1、定义委托对象的接口和类:
public interface Person {
public void killSomeOne(String userName);
}
public class Wangshoucai implements Person{
@Override
public void killSomeOne(String userName) {
System.out.println(userName+",我要干掉你。。。");
}
}
2、定义代理类,实现InvokeHandler接口:
public class DaB implements InvocationHandler{
private Person realPerson;
public DaB(Person realPerson){
this.realPerson = realPerson;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
System.out.println("大B哥幕后准备枪支、刀具和交通工具,奔赴杀场。。。");
method.invoke(realPerson, args);
System.out.println("大B哥带领王守财逃离现场,并收取报酬。");
return null;
}
}
3、客户端,通过获取动态代理对象,调用委托对象的方法:
public class DynamicProxyTest {
public static void main(String[] args) {
//创建委托对象,王守财
Person realPerson = new Wangshoucai();
//创建代理对象、程序处理对象,幕后大B哥
InvocationHandler handler = new DaB(realPerson);
//创建动态代理对象,台前的小混混,马仔A,马仔A明面上代表王守财办事,实质服从大B哥的安排
Person maZaiA = (Person)Proxy.newProxyInstance(
realPerson.getClass().getClassLoader(),
realPerson.getClass().getInterfaces(),
handler);
//马仔A去执行
maZaiA.killSomeOne("坤哥");
}
}
4、控制台输出:
大B哥幕后准备枪支、刀具和交通工具,奔赴杀场。。。
坤哥,我要干掉你。。。
大B哥带领王守财逃离现场,并收取报酬。
注意:如果把动态代理对象的类名打出来,com.sun.proxy.$Proxy0,它既不是Person也不是InvokeHandler类,而是一个动态代理类,由此也可以看出,DaB这个类是代理类,但不是动态代理类,由其生成的对象也不是动态代理对象,而是代理对象。
以上就是动态代理机制基本内容,希望可以帮助理解动态代理到底是怎么回事。