首先明确代理模型中的两个实体:代理类和委托类(处理器)
代理类: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