Java动态代理的应用详解

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


代码如下:

package com.fans.common.proxy;

public interface BusinessProcessor {
  public void processBusiness();
}

代码如下:

package com.fans.common.proxy;
/**
 * 业务处理类
 * @author fanshadoop
 *
 */
public class BusinessProcessorImpl implements BusinessProcessor {

@Override
 public void processBusiness() {
  System.out.println("processing business.....");

}

}

代码如下:

package com.fans.common.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
 * 业务代理类
 * @author fanshadoop
 *
 */
public class BusinessProcessorHandler implements InvocationHandler {

private Object target = null;

BusinessProcessorHandler(Object target) {
  this.target = target;
 }

public Object invoke(Object proxy, Method method, Object[] args)
   throws Throwable {
  System.out
    .println("You can do something here before process your business");
  Object result = method.invoke(target, args);
  System.out
    .println("You can do something here after process your business");
  return result;
 }

}

代码如下:

package com.fans.common.proxy;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;

public class Test {

/**
  * @param args
  */
 public static void main(String[] args) {
  BusinessProcessorImpl bpimpl = new BusinessProcessorImpl();
  BusinessProcessorHandler handler = new BusinessProcessorHandler(bpimpl);
  BusinessProcessor bp = (BusinessProcessor) Proxy.newProxyInstance(
    bpimpl.getClass().getClassLoader(), bpimpl.getClass()
      .getInterfaces(), handler);
  bp.processBusiness();

System.out.println(bp.getClass().getName());
  printClassDefinition(bp.getClass());
 }

public static String getModifier(int modifier) {
  String result = "";
  switch (modifier) {
  case Modifier.PRIVATE:
   result = "private";
  case Modifier.PUBLIC:
   result = "public";
  case Modifier.PROTECTED:
   result = "protected";
  case Modifier.ABSTRACT:
   result = "abstract";
  case Modifier.FINAL:
   result = "final";
  case Modifier.NATIVE:
   result = "native";
  case Modifier.STATIC:
   result = "static";
  case Modifier.SYNCHRONIZED:
   result = "synchronized";
  case Modifier.STRICT:
   result = "strict";
  case Modifier.TRANSIENT:
   result = "transient";
  case Modifier.VOLATILE:
   result = "volatile";
  case Modifier.INTERFACE:
   result = "interface";
  }
  return result;
 }

public static void printClassDefinition(Class clz) {

String clzModifier = getModifier(clz.getModifiers());
  if (clzModifier != null && !clzModifier.equals("")) {
   clzModifier = clzModifier + " ";
  }
  String superClz = clz.getSuperclass().getName();
  if (superClz != null && !superClz.equals("")) {
   superClz = "extends " + superClz;
  }
  Class[] interfaces = clz.getInterfaces();
  String inters = "";
  for (int i = 0; i < interfaces.length; i++) {
   if (i == 0) {
    inters += "implements ";
   }
   inters += interfaces[i].getName();
  }
  System.out.println(clzModifier + clz.getName() + " " + superClz + " "
    + inters);
  System.out.println("{");
  Field[] fields = clz.getDeclaredFields();
  for (int i = 0; i < fields.length; i++) {
   String modifier = getModifier(fields[i].getModifiers());
   if (modifier != null && !modifier.equals("")) {
    modifier = modifier + " ";
   }
   String fieldName = fields[i].getName();
   String fieldType = fields[i].getType().getName();
   System.out.println("    " + modifier + fieldType + " " + fieldName
     + ";");
  }

System.out.println();

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

String modifier = getModifier(method.getModifiers());
   if (modifier != null && !modifier.equals("")) {
    modifier = modifier + " ";
   }
   String methodName = method.getName();
   Class returnClz = method.getReturnType();
   String retrunType = returnClz.getName();

Class[] clzs = method.getParameterTypes();
   String paraList = "(";
   for (int j = 0; j < clzs.length; j++) {
    paraList += clzs[j].getName();
    if (j != clzs.length - 1) {
     paraList += ", ";
    }
   }
   paraList += ")";
   clzs = method.getExceptionTypes();
   String exceptions = "";
   for (int j = 0; j < clzs.length; j++) {
    if (j == 0) {
     exceptions += "throws ";
    }
    exceptions += clzs[j].getName();
    if (j != clzs.length - 1) {
     exceptions += ", ";
    }
   }
   exceptions += ";";
   String methodPrototype = modifier + retrunType + " " + methodName
     + paraList + exceptions;

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

运行结果:


代码如下:

You can do something here before process your business
processing business.....
You can do something here after process your business
$Proxy0
$Proxy0 extends java.lang.reflect.Proxy implements com.fans.common.proxy.BusinessProcessor
{
    java.lang.reflect.Method m1;
    java.lang.reflect.Method m3;
    java.lang.reflect.Method m0;
    java.lang.reflect.Method m2;

boolean equals(java.lang.Object);
    java.lang.String toString();
    int hashCode();
    void processBusiness();
}

类BusinessProcessorHandler实现了InvocationHandler接口的invoke方法,这个类就是Proxy最终调用固定接口方法。

很明显,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方法啦!

(0)

相关推荐

  • JAVA提高第八篇 动态代理技术

    对于动态代理,学过AOP的应该都不会陌生,因为代理是实现AOP功能的核心和关键技术.那么今天我们将开始动态代理的学习: 一.引出动态代理 生活中代理应该是很常见的,比如你可以通过代理商去买电脑,也可以直接找厂商买电脑,最终都是买到了电脑.程序中也一样存在代理的情况,比如要为已经存在的多个具有相同接口的目标类的各个方法增加一些系统功能,例如:异常处理.日志.计算方法耗时等等,那么我们会怎么做呢? 1.会编写一个与目标类拥有相同接口的代理类,代理类的每个方法调用目标类的相同方法,然后在调用方法前后加

  • 基于接口实现java动态代理示例

    Subject.java 复制代码 代码如下: package _20140416_; import java.util.List; public interface Subject {   public String say(String name,int age);   public List<Person> getAllList(String name);} RealSubject.java 复制代码 代码如下: package _20140416_; import java.util.

  • java使用动态代理来实现AOP(日志记录)的实例代码

    下面是一个AOP实现的简单例子: 首先定义一些业务方法: 复制代码 代码如下: /** * Created with IntelliJ IDEA. * Author: wangjie  email:tiantian.china.2@gmail.com * Date: 13-9-23 * Time: 下午3:49 */public interface BussinessService {    public String login(String username, String password

  • java动态代理(jdk与cglib)详细解析

    JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务. 按照代理的创建时期,代理类可以分为两种. 静态代理:由程序员创建或特定工具自动生成源代码,再对其编译.在程序运行前,代理类的.class文件就已经

  • 代理模式之Java动态代理实现方法

    今天一个偶然的机会我突然想看看JDK的动态代理,因为以前也知道一点,而且只是简单的想测试一下使用,使用很快里就写好了这么几个接口和类:接口类:UserService.java 复制代码 代码如下: package com.yixi.proxy;public interface UserService {    public int save() ;    public void update(int id);} 实现类:UserServiceImpl.java 复制代码 代码如下: packag

  • java动态代理和cglib动态代理示例分享

    java动态代理类可以分为两种. 静态代理:由程序员创建或特定工具自动生成源代码,再对其编译.在程序运行前,代理类的.class文件就已经存在了. 动态代理:在程序运行时,运用反射机制动态创建而成. 一.首先我们进行java动态代理的演示. 现在我们有一个简单的业务接口Saying,如下: 复制代码 代码如下: package testAOP;public interface Saying {public void sayHello(String name);    public void ta

  • java jdk动态代理详解

    jdk动态代理要对一个类进行代理,被代理的类必须实现至少一个接口,并且只有接口中的方法才能被代理. jdk实现动态代理一般分为三步: 1. 编写接口和实现类. 2. 写一个处理器,该处理器实现InvocationHandler接口,该接口只有一个方法,其签名为public Object invoke(Object proxy, Method method, Object[] args)throws Throwable;可在该处理器的实现方法中,在方法调用前和调用后加入自己的代码,从而进行动态拦截

  • java代理模式与动态代理模式详解

    1.代理模式 所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动.在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之前起到中介的作用.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. 生活中的例子:过年加班比较忙,没空去买火车票,这时可以打个电话到附近的票务中心,叫他们帮你买张回家的火车票,当然这会附加额外的劳务费.但要清楚票务中心自己并不卖票,只有火车站才真正卖票,票务中心卖给你的票其实是通过火车站实现的.这点很重要!

  • 十分钟理解Java中的动态代理

    若代理类在程序运行前就已经存在,那么这种代理方式被成为 静态代理 ,这种情况下的代理类通常都是我们在Java代码中定义的. 通常情况下, 静态代理中的代理类和委托类会实现同一接口或是派生自相同的父类. 一.概述 1. 什么是代理 我们大家都知道微商代理,简单地说就是代替厂家卖商品,厂家"委托"代理为其销售商品.关于微商代理,首先我们从他们那里买东西时通常不知道背后的厂家究竟是谁,也就是说,"委托者"对我们来说是不可见的;其次,微商代理主要以朋友圈的人为目标客户,这就

  • java实现动态代理方法浅析

    一些Java项目中在mybatis与spring整合中有MapperScannerConfigurer的使用,该类通过反向代理自动生成基于接口的动态代理类. 有鉴于此,本文浅析了java的动态代理. 本文使用动态代理模拟处理事务的拦截器. 接口: public interface UserService { public void addUser(); public void removeUser(); public void searchUser(); } 实现类: public class

随机推荐