java动态代理


java动态代理
两种:
1.JDK Proxy
2.cglib

JDK动态代理与CGLib动态代理均是实现Spring AOP的基础。

一、JDK Proxy
1.示例:
/**
 * 具体实现类的接口
 */
public interface Subject {

    public void rent();
    
}

/**
 * 具体实现类
 */
public class RealSubject implements Subject {

    public void rent() {
        System.out.println("具体实现类的方法");
    }
    
}

/**
 * 创建动态代理类
 */
public class DynamicProxy implements InvocationHandler {

    //这个就是我们要代理的真实对象
    private Object subject;
    
    //构造方法,给我们要代理的真实对象赋初值
    public DynamicProxy(Object subject){
        this.subject = subject;
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        //在代理真实对象前我们可以添加一些自己的操作
        System.out.println("之前");
        
        //当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
        method.invoke(subject, args);
        
        //  在代理真实对象后我们也可以添加一些自己的操作
        System.out.println("之后");
        
        return null;
    }

}

/**
 * test
 */
public class Client {

    public static void main(String[] args){
        //我们要代理的真实对象
        Subject realSubject = new RealSubject();

        //我们要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法的
        InvocationHandler handler = new DynamicProxy(realSubject);

        /*
         * 通过Proxy的newProxyInstance方法来创建我们的代理对象,我们来看看其三个参数
         * 第一个参数 handler.getClass().getClassLoader() ,我们这里使用handler这个类的ClassLoader对象来加载我们的代理对象
         * 第二个参数realSubject.getClass().getInterfaces(),我们这里为代理对象提供的接口是真实对象所实行的接口,表示我要代理的是该真实对象,这样我就能调用这组接口中的方法了
         * 第三个参数handler, 我们这里将这个代理对象关联到了上方的 InvocationHandler 这个对象上
         */
        Subject subject = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject
                .getClass().getInterfaces(), handler);
        
        subject.rent();
        
    }
    
}
2.源码分析

TODO

一个典型的动态代理创建对象过程可分为以下四个步骤:

1、通过实现InvocationHandler接口创建自己的调用处理器 IvocationHandler handler = new InvocationHandlerImpl(...);

2、通过为Proxy类指定ClassLoader对象和一组interface创建动态代理类
Class clazz = Proxy.getProxyClass(classLoader,new Class[]{...});

3、通过反射机制获取动态代理类的构造函数,其参数类型是调用处理器接口类型
Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});

4、通过构造函数创建代理类实例,此时需将调用处理器对象作为参数被传入
Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler));

生成的代理对象ProxySubject继承Proxy类实现Subject接口,
实现的Subject的方法实际调用处理器的invoke方法,
而invoke方法利用反射调用的是被代理对象的的方法(Object result = method.invoke(proxied,args))

4.生成的代理类源码

原文:http://blog.csdn.net/scplove/article/details/52451899
原文:http://rejoy.iteye.com/blog/1627405

import java.lang.reflect.*;  
 
public final class $Proxy11 extends Proxy  
    implements UserService  
{  
 
    // 构造方法,参数就是刚才传过来的MyInvocationHandler类的实例  
    public $Proxy11(InvocationHandler invocationhandler)  
    {  
        super(invocationhandler);  
    }  
 
    public final boolean equals(Object obj)  
    {  
        try  
        {  
            return ((Boolean)super.h.invoke(this, m1, new Object[] {  
                obj  
            })).booleanValue();  
        }  
        catch(Error _ex) { }  
        catch(Throwable throwable)  
        {  
            throw new UndeclaredThrowableException(throwable);  
        }  
    }  
 
    /**
     * 这个方法是关键部分
     */  
    public final void add()  
    {  
        try  
        {  
            // 实际上就是调用MyInvocationHandler的public Object invoke(Object proxy, Method method, Object[] args)方法,第二个问题就解决了  
            super.h.invoke(this, m3, null);  
            return;  
        }  
        catch(Error _ex) { }  
        catch(Throwable throwable)  
        {  
            throw new UndeclaredThrowableException(throwable);  
        }  
    }  
 
    public final int hashCode()  
    {  
        try  
        {  
            return ((Integer)super.h.invoke(this, m0, null)).intValue();  
        }  
        catch(Error _ex) { }  
        catch(Throwable throwable)  
        {  
            throw new UndeclaredThrowableException(throwable);  
        }  
    }  
 
    public final String toString()  
    {  
        try  
        {  
            return (String)super.h.invoke(this, m2, null);  
        }  
        catch(Error _ex) { }  
        catch(Throwable throwable)  
        {  
            throw new UndeclaredThrowableException(throwable);  
        }  
    }  
 
    private static Method m1;  
    private static Method m3;  
    private static Method m0;  
    private static Method m2;  
 
    // 在静态代码块中获取了4个方法:Object中的equals方法、UserService中的add方法、Object中的hashCode方法、Object中toString方法  
    static   
    {  
        try  
        {  
            m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] {  
                Class.forName("java.lang.Object")  
            });  
            m3 = Class.forName("dynamic.proxy.UserService").getMethod("add", new Class[0]);  
            m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);  
            m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);  
        }  
        catch(NoSuchMethodException nosuchmethodexception)  
        {  
            throw new NoSuchMethodError(nosuchmethodexception.getMessage());  
        }  
        catch(ClassNotFoundException classnotfoundexception)  
        {  
            throw new NoClassDefFoundError(classnotfoundexception.getMessage());  
        }  
    }  
}  

二、cglib Proxy

http://blog.csdn.net/yakoo5/article/details/9099133/

JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢,这就需要CGLib了。
CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,
并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。

1.示例
import java.lang.reflect.*;  
 
public final class $Proxy11 extends Proxy  
    implements UserService  
{  
 
    // 构造方法,参数就是刚才传过来的MyInvocationHandler类的实例  
    public $Proxy11(InvocationHandler invocationhandler)  
    {  
        super(invocationhandler);  
    }  
 
    public final boolean equals(Object obj)  
    {  
        try  
        {  
            return ((Boolean)super.h.invoke(this, m1, new Object[] {  
                obj  
            })).booleanValue();  
        }  
        catch(Error _ex) { }  
        catch(Throwable throwable)  
        {  
            throw new UndeclaredThrowableException(throwable);  
        }  
    }  
 
    /**
     * 这个方法是关键部分
     */  
    public final void add()  
    {  
        try  
        {  
            // 实际上就是调用MyInvocationHandler的public Object invoke(Object proxy, Method method, Object[] args)方法,第二个问题就解决了  
            super.h.invoke(this, m3, null);  
            return;  
        }  
        catch(Error _ex) { }  
        catch(Throwable throwable)  
        {  
            throw new UndeclaredThrowableException(throwable);  
        }  
    }  
 
    public final int hashCode()  
    {  
        try  
        {  
            return ((Integer)super.h.invoke(this, m0, null)).intValue();  
        }  
        catch(Error _ex) { }  
        catch(Throwable throwable)  
        {  
            throw new UndeclaredThrowableException(throwable);  
        }  
    }  
 
    public final String toString()  
    {  
        try  
        {  
            return (String)super.h.invoke(this, m2, null);  
        }  
        catch(Error _ex) { }  
        catch(Throwable throwable)  
        {  
            throw new UndeclaredThrowableException(throwable);  
        }  
    }  
 
    private static Method m1;  
    private static Method m3;  
    private static Method m0;  
    private static Method m2;  
 
    // 在静态代码块中获取了4个方法:Object中的equals方法、UserService中的add方法、Object中的hashCode方法、Object中toString方法  
    static   
    {  
        try  
        {  
            m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] {  
                Class.forName("java.lang.Object")  
            });  
            m3 = Class.forName("dynamic.proxy.UserService").getMethod("add", new Class[0]);  
            m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);  
            m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);  
        }  
        catch(NoSuchMethodException nosuchmethodexception)  
        {  
            throw new NoSuchMethodError(nosuchmethodexception.getMessage());  
        }  
        catch(ClassNotFoundException classnotfoundexception)  
        {  
            throw new NoClassDefFoundError(classnotfoundexception.getMessage());  
        }  
    }  
}  

2.反编译生成的代理对象源码
http://www.cnblogs.com/ctgulong/p/5011614.html

三、JDK/CGLIB两种动态代理--比较

JDK创建动态代理,基于接口,需要具体实现类实现接口,
CGLIB创建动态代理,基于子类。final方法,无法进行代理。

CGLib创建的动态代理对象性能比JDK创建的动态代理对象的性能高不少,
但是CGLib在创建代理对象时所花费的时间却比JDK多得多,

所以对于单例的对象,因为无需频繁创建对象,用CGLib合适,反之,使用JDK方式要更为合适一些。


四、Spring AOP分析

http://blog.csdn.net/jzq114/article/details/51346083

TODO




你可能感兴趣的:(java,java动态代理)