ITPub博客

首页 > 应用开发 > Java > Java Proxy动态代理

Java Proxy动态代理

原创 Java 作者:百联达 时间:2016-12-06 11:24:03 0 删除 编辑
一:背景

Spring主要有两大思想,一个是IoC,另一个就是AOP.而AOP的原理就是java的动态代理机制.

二:概念

动态代理其实就是java.lang.reflect.Proxy类动态的根据您指定的所有接口生成一个class BYTE,该class会继承Proxy类,并实现所有你指定的接口(您在参数中传入的接口数组);然后再利用您指定的classloader将 class BYTE加载进系统,最后生成这样一个类的对象,并初始化该对象的一些值,如invocationHandler,以即所有的接口对应的Method成员。 初始化之后将对象返回给调用的客户端

三:解析

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

InvocationHandler:
每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个Handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。我们来看看InvocationHandler这个接口的唯一一个方法 invoke 方法:
Object invoke(Object proxy, Method method, Object[] args) throws Throwable
我们看到这个方法一共接受三个参数,那么这三个参数分别代表什么呢?

proxy:  指代我们所代理的那个真实对象
method:  指代的是我们所要调用真实对象的某个方法的Method对象
args:  指代的是调用真实对象某个方法时接受的参数

Proxy:

Proxy这个类的作用就是用来动态创建一个代理对象的类,它提供了许多的方法,但是我们用的最多的就是 newProxyInstance 这个方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,  InvocationHandler h)  throws IllegalArgumentException
这个方法的作用就是得到一个动态的代理对象,其接收三个参数,我们来看看这三个参数所代表的含义:
loader:  一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载
interfaces:  一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了
h: 一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上


四:案例

业务接口:

点击(此处)折叠或打开

  1. public interface BusinessProcessor {
  2.     public void processBusiness();
  3. }
业务实现:

点击(此处)折叠或打开

  1. public class BusinessProcessorImpl implements BusinessProcessor{

  2.     /* (non-Javadoc)
  3.      * @see com.enjoylink.gmap.mongodb.demo.BusinessProcessor#processBusiness()
  4.      */
  5.     @Override
  6.     public void processBusiness() {
  7.         
  8.         System.out.println("===========处理业务============");
  9.     }

  10. }
业务代理:

点击(此处)折叠或打开

  1. public class BusinessProcessorHandler implements InvocationHandler {

  2.     private Object target = null;

  3.     BusinessProcessorHandler(Object target) {
  4.         this.target = target;
  5.     }

  6.     /*
  7.      * (non-Javadoc)
  8.      *
  9.      * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object,
  10.      * java.lang.reflect.Method, java.lang.Object[])
  11.      */
  12.     @Override
  13.     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  14.         
  15.         System.out.println("=========业务处理------前的操作=========");
  16.         Object result=method.invoke(target, args);
  17.         System.out.println("=========业务处理------后的操作=========");
  18.         return result;
  19.     }

  20. }
测试:

点击(此处)折叠或打开

  1. public class BusinessProcessorTest {

  2.     public static void main(String[] args) {
  3.         BusinessProcessorImpl bpImpl = new BusinessProcessorImpl();
  4.         BusinessProcessorHandler handler = new BusinessProcessorHandler(bpImpl);

  5.         BusinessProcessor bp = (BusinessProcessor) Proxy.newProxyInstance(bpImpl.getClass().getClassLoader(),
  6.                 bpImpl.getClass().getInterfaces(), handler);

  7.         bp.processBusiness();
  8.         System.out.println(bp.getClass().getName());

  9.         Class clz = bp.getClass();
  10.         printClassDefinition(clz);

  11.     }

  12.     public static String getModifier(int modifier) {
  13.         String result = "";
  14.         switch (modifier) {
  15.             case Modifier.PRIVATE:
  16.                 result = "private";
  17.             case Modifier.PUBLIC:
  18.                 result = "public";
  19.             case Modifier.PROTECTED:
  20.                 result = "protected";
  21.             case Modifier.ABSTRACT:
  22.                 result = "abstract";
  23.             case Modifier.FINAL:
  24.                 result = "final";
  25.             case Modifier.NATIVE:
  26.                 result = "native";
  27.             case Modifier.STATIC:
  28.                 result = "static";
  29.             case Modifier.SYNCHRONIZED:
  30.                 result = "synchronized";
  31.             case Modifier.STRICT:
  32.                 result = "strict";
  33.             case Modifier.TRANSIENT:
  34.                 result = "transient";
  35.             case Modifier.VOLATILE:
  36.                 result = "volatile";
  37.             case Modifier.INTERFACE:
  38.                 result = "interface";
  39.         }
  40.         return result;
  41.     }

  42.     public static void printClassDefinition(Class clz) {

  43.         String clzModifier = getModifier(clz.getModifiers());
  44.         if (clzModifier != null && !clzModifier.equals("")) {
  45.             clzModifier = clzModifier + " ";
  46.         }
  47.         String superClz = clz.getSuperclass().getName();
  48.         if (superClz != null && !superClz.equals("")) {
  49.             superClz = "extends " + superClz;
  50.         }

  51.         Class[] interfaces = clz.getInterfaces();

  52.         String inters = "";
  53.         for (int i = 0; i < interfaces.length; i++) {
  54.             if (i == 0) {
  55.                 inters += "implements ";
  56.             }
  57.             inters += interfaces[i].getName();
  58.         }

  59.         System.out.println(clzModifier + clz.getName() + " " + superClz + " " + inters);
  60.         System.out.println("{");

  61.         Field[] fields = clz.getDeclaredFields();
  62.         for (int i = 0; i < fields.length; i++) {
  63.             String modifier = getModifier(fields[i].getModifiers());
  64.             if (modifier != null && !modifier.equals("")) {
  65.                 modifier = modifier + " ";
  66.             }
  67.             String fieldName = fields[i].getName();
  68.             String fieldType = fields[i].getType().getName();
  69.             System.out.println(" " + modifier + fieldType + " " + fieldName + ";");
  70.         }

  71.         System.out.println();

  72.         Method[] methods = clz.getDeclaredMethods();
  73.         for (int i = 0; i < methods.length; i++) {
  74.             Method method = methods[i];

  75.             String modifier = getModifier(method.getModifiers());
  76.             if (modifier != null && !modifier.equals("")) {
  77.                 modifier = modifier + " ";
  78.             }

  79.             String methodName = method.getName();

  80.             Class returnClz = method.getReturnType();
  81.             String retrunType = returnClz.getName();

  82.             Class[] clzs = method.getParameterTypes();
  83.             String paraList = "(";
  84.             for (int j = 0; j < clzs.length; j++) {
  85.                 paraList += clzs[j].getName();
  86.                 if (j != clzs.length - 1) {
  87.                     paraList += ", ";
  88.                 }
  89.             }
  90.             paraList += ")";

  91.             clzs = method.getExceptionTypes();
  92.             String exceptions = "";
  93.             for (int j = 0; j < clzs.length; j++) {
  94.                 if (j == 0) {
  95.                     exceptions += "throws ";
  96.                 }

  97.                 exceptions += clzs[j].getName();

  98.                 if (j != clzs.length - 1) {
  99.                     exceptions += ", ";
  100.                 }
  101.             }

  102.             exceptions += ";";

  103.             String methodPrototype = modifier + retrunType + " " + methodName + paraList + exceptions;

  104.             System.out.println(" " + methodPrototype);

  105.         }
  106.         System.out.println("}");
  107.     }

  108. }
测试结果:

点击(此处)折叠或打开

  1. =========业务处理------前的操作=========
  2. ===========处理业务============
  3. =========业务处理------后的操作=========
  4. com.sun.proxy.$Proxy0
  5. com.sun.proxy.$Proxy0 extends java.lang.reflect.Proxy implements com.enjoylink.gmap.mongodb.demo.BusinessProcessor
  6. {
  7.     java.lang.reflect.Method m1;
  8.     java.lang.reflect.Method m2;
  9.     java.lang.reflect.Method m3;
  10.     java.lang.reflect.Method m0;

  11.     boolean equals(java.lang.Object);
  12.     java.lang.String toString();
  13.     int hashCode();
  14.     void processBusiness();
  15. }

Proxy.newProxyInstance方法会做如下几件事:

 

1,根据传入的第二个参数interfaces动态生成一个类,实现interfaces中的接口,该例中即BusinessProcessor接口的processBusiness方法。并且继承了Proxy类,重写了hashcode,toString,equals等三个方法。具体实现可参看 ProxyGenerator.generateProxyClass(...); 该例中生成了$Proxy0类

 

2,通过传入的第一个参数classloder将刚生成的类加载到jvm中。即将$Proxy0类load

 

3,利用第三个参数,调用$Proxy0的$Proxy0(InvocationHandler)构造函数 创建$Proxy0的对象,并且用interfaces参数遍历其所有接口的方法,并生成Method对象初始化对象的几个Method成员变量

 

4,将$Proxy0的实例返回给客户端。

我们再看客户端怎么调就清楚了。

 

1,客户端拿到的是$Proxy0的实例对象,由于$Proxy0继承了BusinessProcessor,因此转化为BusinessProcessor没任何问题。

 

BusinessProcessor bp = (BusinessProcessor)Proxy.newProxyInstance(....);

 

2,bp.processBusiness();

 

实际上调用的是$Proxy0.processBusiness();那么$Proxy0.processBusiness()的实现就是通过InvocationHandler去调用invoke方法。

五:总结

代理模式最大的特点就是代理类和实际业务类实现同一个接口(或继承同一父类),代理对象持有一个实际对象的引用,外部调用时操作的是代理对象,而在代理对象的内部实现中又会去调用实际对象的操作
 Java动态代理其实内部也是通过Java反射机制来实现的,即已知的一个对象,然后在运行时动态调用其方法,这样在调用前后作一些相应的处理.

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/28624388/viewspace-2129828/ ,如需转载,请注明出处,否则将追究法律责任。

上一篇: Java Filter过滤器
下一篇: Java Annotation 注解
请登录后发表评论 登录
全部评论
15年以上互联网经验,先后从事过制造业,证券业,物业行业和物流行业信息系统和互联网产品的设计落地实施,8年系统架构经验。最近关注企业数字化转型、财务数字化服务共享、大语言模型、Kubernetes微服务架构和Istio微服务治理框架。

注册时间:2013-02-05

  • 博文量
    332
  • 访问量
    1265640