JDK中的Proxy技术实现AOP功能

来源:互联网 发布:交通大学网络教育报名 编辑:程序博客网 时间:2024/05/16 15:48

     学习一门技术从源头开始学习会比较有成就感,好多大神就是对各个版本如数家珍,崇拜!

     这里的内容主要是参考黎活明老师的Spring2.5视频,加上自己揣摩源代码时的一些理解。



package com.zgy.aop.simple;import pojo.HelloWorldI;import pojo.HelloWorldImpl;/** * 测试类. *  * * <pre> * datemodifier reason * 2013-4-26zgy     create * </pre> */public class Main {    public static void main(String[] args) {       //实例化工厂      JDKProxyFactory jdkProxyFactory = new JDKProxyFactory();      //生成代理类实例      Object object = jdkProxyFactory.createProxyInstance(new HelloWorldImpl());      //通过接口调用      HelloWorldI helloWorld = (HelloWorldI)object;      helloWorld.sayHello("ZGY");             }}



package com.zgy.aop.simple;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;/** * 重写调用处理器invoke方法添加上自己的处理逻辑. *  * * <pre> * datemodifier reason * 2013-4-26zgy     create * </pre> */public class MyInvocationHandler implements InvocationHandler{    /**     * 被代理的类.     */    private Object targetObject;        public MyInvocationHandler(Object targetObject) {        this.targetObject = targetObject;    }        /**     *      * AOP逻辑处理.     * @args 参数     * @param method 拦截到的方法     * @param proxy JDKProxyFactory.createProxyInstance方法产生的对象既代理类实例     * <pre>     * date         modifier reason     * 2013-4-26    zgy      create     * </pre>     */    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        System.out.println("记录日志");        return method.invoke(targetObject, args);    }}


    

    

package com.zgy.aop.simple;import java.lang.reflect.Proxy;/** *  代理生成工厂. *  * * <pre> * datemodifier reason * 2013-4-26zgy     create * </pre> */public class JDKProxyFactory{    /**     * 被代理的类.     */    private Object targetObject;        /**     * 返回一个指定接口的代理类实例,方法调用指派到指定的调用处理程序。     * @param targetObject 被代理的类     * @return     *     * <pre>     * datemodifier reason     * 2013-4-26zgy     create     * </pre>     */    public Object createProxyInstance(Object targetObject) {        this.targetObject = targetObject;        //返回一个指定接口的代理类实例,传入了被代理的类的加载器,被代理的类的接口,和处理器        return Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(),                 this.targetObject.getClass().getInterfaces(), new MyInvocationHandler(targetObject));    }}

这里分析下代理类实例是如何生成的

处理这段逻辑的的是java.lang.reflect.Proxy这个类,源代码大家应该都可以看得到,这里就截取一些片段:

proxy.newProxyInstance方法就是执行以下代码:
Class cl = getProxyClass(loader, interfaces);//这里是重点
Constructor cons = cl.getConstructor(constructorParams);//下面这两句好理解,就是传入一个处理器
return (Object) cons.newInstance(new Object[] { h });

下面我们看看getProxyClass(loader, interfaces)方法做了什么:
byte[] proxyClassFile =    ProxyGenerator.generateProxyClass(proxyName, interfaces);//将我们传入的HelloWorldI编译为字节码
Class proxyClass = defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length);//调用本地方法生成最终结果,传入的参数有HelloWorldImpl类加载
器,HelloWorldI编译为字节码,如果从结果来反推的,可以揣测着里发生了什么,在测试类中我们很简单的只是执行了以下几句就实现了AOP:
      //object == (HelloWorldImpl)proxyClass

      Object object = jdkProxyFactory.createProxyInstance(new HelloWorldImpl());
      //通过接口调用
      HelloWorldI helloWorld = (HelloWorldI)object;
      helloWorld.sayHello("ZGY");
所以proxyClass的字节码里肯定是糅合了MyInvocationHandler的System.out.println("记录日志")

也就是处理器的逻辑代码,在下一篇文章里,我会参考网上的资料进一步分析