还可以 发表于 2013-2-3 10:27:55

java中的动态代理

首先明确代理模型中的两个实体:代理类和委托类(处理器)
代理类:JVM中的代理类都是Proxy的子类,并且其字节码是由JVM动态产生的,代理类字节码字节数组是调用ProxyGenerator的generateProxyClass(String arg0, Class[] interfaces)方法生成的。代理类会将请求委派给委托类执行。
委托类:也称作处理器,其会实现接口InvocationHandler,其接口中只有一个方法invoke,实际的处理逻辑都会放入其中。
 
关于代理类的对象的产生
这是通过Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)方法进行产生的,解释一下其中的三个参数,loader为装载此代理类字节码的类装载器,interfaces会作为最终产生代理类字节码的材料来源之一(ProxyGenerator.generateProxyClass(String arg0, Class[] interfaces)),h为处理器.
 
关于JVM生成的代理类的类名
都为ProxyN,其中N为当前JVM实例中生成的代理类的个数,由一个静态整型变量记录,创造一个N值累加一下。每个代理类的class对象都会被缓存在Proxy的一个map对象中,这样做的好处是当在同一个classloader中需要同一个代理类时,就不需要重复去创造已有的代理类了,直接从map中取用class对象即可。减少了字节码构建和装载时JVM的性能消耗。
 
使用代理类的好处
因为代理类是使用反射在JVM运行时动态产生的,所以其使用有很好的灵活性,可以在任何业务逻辑之前和之后加入自己想加入的代码,spring中的aop就使用了此项技术。
 
自己写了一个代理的demo:
在这个demo中,想在Student的say方法逻辑之前和之后加入其它代码,处理器为Teacher。
接口People:
package com.proxy;
 
public interface People {
  public void say();
}
 
Student实体:
package com.proxy;
 
public class Student implements People {
 
         @Override
         public void say() {
             System.out.println("Student say");
         }
 
}
 
Teacher实体:
package com.proxy;
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
 
public class Teacher implements InvocationHandler {
    private People people;
         public Teacher(People people){
             this.people = people;
    }
         @Override
         public Object invoke(Object proxy, Method method, Object[] args)
                            throws Throwable {
                   System.out.println("before");
                   people.say();
                   System.out.println("teacher say");
        System.out.println("after");
                   return null;
         }
 
}
测试类ProxyTest:
package com.proxy;
import java.lang.reflect.Proxy;
public class ProxyTest{
    public static void main(String[] aa){
             Student student = new Student();
             Teacher teacher = new Teacher(student);
             People people = (People)Proxy.newProxyInstance(student.getClass().getClassLoader(), student.getClass().getInterfaces(), teacher);
             people.say();
        System.out.println(Proxy.isProxyClass(people.getClass()));
        System.out.println(people.getClass().getName());
    }
 
}
 
输出结果为:
before
Student say
teacher say
after
true
$Proxy0
这里再附上一篇详细讲解java中动态代理的文章http://www.ibm.com/developerworks/cn/java/j-lo-proxy1/
这里还有一篇动态代理和静态代理对比的文章http://blog.csdn.net/sunyujia/article/details/2500684
页: [1]
查看完整版本: java中的动态代理