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]