码迷,mamicode.com
首页 > 其他好文 > 详细

动态代理 (JDK代理)

时间:2016-07-23 07:39:17      阅读:242      评论:0      收藏:0      [点我收藏+]

标签:java   proxy   


1、动态代理用到的类和方法

动态代理涉及到的类是java.lang.reflect.Proxy,主要是用到它的newProxyInstance方法。

public class Proxy implements java.io.Serializable {

    /** prefix for all proxy class names */
    private final static String proxyClassNamePrefix = "$Proxy";

   /**
     * Returns an instance of a proxy class for the specified interfaces
     * that dispatches method invocations to the specified invocation
     * handler.  This method is equivalent to:
     * <pre>
     *     Proxy.getProxyClass(loader, interfaces).
     *         getConstructor(new Class[] { InvocationHandler.class }).
     *         newInstance(new Object[] { handler });
     * </pre>
     *
     * <p>{@code Proxy.newProxyInstance} throws
     * {@code IllegalArgumentException} for the same reasons that
     * {@code Proxy.getProxyClass} does.
     *
     * @param   loader the class loader to define the proxy class
     * @param   interfaces the list of interfaces for the proxy class
     *          to implement
     * @param   h the invocation handler to dispatch method invocations to
     * @return  a proxy instance with the specified invocation handler of a
     *          proxy class that is defined by the specified class loader
     *          and that implements the specified interfaces
     * @throws  IllegalArgumentException if any of the restrictions on the
     *          parameters that may be passed to {@code getProxyClass}
     *          are violated
     * @throws  NullPointerException if the {@code interfaces} array
     *          argument or any of its elements are {@code null}, or
     *          if the invocation handler, {@code h}, is
     *          {@code null}
     */
    @CallerSensitive
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
        if (h == null) {
            throw new NullPointerException();
        }

        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            checkProxyAccess(Reflection.getCallerClass(), loader, interfaces);
        }

        /*
         * Look up or generate the designated proxy class.
         */
        Class<?> cl = getProxyClass0(loader, interfaces);

        /*
         * Invoke its constructor with the designated invocation handler.
         */
        try {
            final Constructor<?> cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
            if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) {
                // create proxy instance with doPrivilege as the proxy class may
                // implement non-public interfaces that requires a special permission
                return AccessController.doPrivileged(new PrivilegedAction<Object>() {
                    public Object run() {
                        return newInstance(cons, ih);
                    }
                });
            } else {
                return newInstance(cons, ih);
            }
        } catch (NoSuchMethodException e) {
            throw new InternalError(e.toString());
        }
    }

}


2、动态代理涉及到几个概念

动态代理涉及到几个概念:Proxy、proxy class、proxy interface、proxy instance、InvocationHandler、target class、target instance。


示例:明星-->经纪人,经纪人是明星的代理。


target class是我们的原始类型,target instance是target class的实例。


proxy class是代理类,proxy instance是proxy class的实例。


proxy interface是proxy class实现的接口。


proxy instance是target instance的代理类的实例。在使用动态代理时,我们原有的对象是target instance,真正使用的对象是proxy instance。


当调用proxy instance实例上的method时(注意,这些method是定义在proxy interface接口上的),会调用InvocationHandler的invoke方法。在invoke方法内,对原来的target instance的方法进行扩展。


注意:target class必须实现接口




技术分享

java.lang.reflect.Proxy类提供了创建proxy classes和proxy instance的方法。java.lang.reflect.Proxy类是所有proxy classes的子类。


【Proxy与proxy class和proxy instance的关系】

Proxy provides static methods for creating dynamic proxy classes and instances, and it is also the superclass of all dynamic proxy classes created by those methods. 


【proxy class】

A dynamic proxy class (simply referred to as a proxy class below) is a class that implements a list of interfaces specified at runtime when the class is created, with behavior as described below.


【proxy interface和proxy class的关系】

A proxy interface is such an interface that is implemented by a proxy class.


【proxy instance和proxy class的关系】

A proxy instance is an instance of a proxy class.


【proxy instance和invocation handler的关系】

Each proxy instance has an associated invocation handler object, which implements the interface InvocationHandler.


【proxy interface是proxy class的接口,proxy instance是proxy class的实例。当调用proxy instance的某个proxy interface的method时,会执行InvocationHandler的invoke方法。】

A method invocation on a proxy instance through one of its proxy interfaces will be dispatched to the invoke method of the instance‘s invocation handler, passing the proxy instance, a java.lang.reflect.Method object identifying the method that was invoked, and an array of type Object containing the arguments. 


3、示例代码

To create a proxy for some interface Foo: 

     InvocationHandler handler = new MyInvocationHandler(...);
     Class proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), new Class[] { Foo.class });
     Foo f = (Foo) proxyClass.getConstructor(new Class[] { InvocationHandler.class }).
			newInstance(new Object[] { handler });

or more simply: 

     Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
                                          new Class[] { Foo.class },
                                          handler);


下面是newProxyInstance方法的参数

    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)


假设我们正在使用一个(实现了某个接口的)实例target

loader: target.getClass().getClassLoader()

interfaces: target.getClass().getInterfaces()


假设我们正在使用一个接口Foo

loader: Foo.class.getClassLoader()

interfaces: new Class[] {Foo.class}


	public void test()
	{
		final UserDao target = new UserDao();
		Class<?>[] interfaces = target.getClass().getInterfaces();
		
		IPlay proxy = (IPlay) Proxy.newProxyInstance(
											target.getClass().getClassLoader(), 
											new Class[]{IFly.class}, 
											//target.getClass().getInterfaces(),
											new InvocationHandler()
											{
												@Override
												public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
												{
													System.out.println("hello--begin");
													Object result = method.invoke(target, args);
													System.out.println("hello--end");
													return result;
												}
											});
		
		proxy.play();
		System.out.println("------------------------------");
		IFly dao = (IFly)proxy;
		dao.fly();
		System.out.println("------------------------------");
		ISwim dao2 = (ISwim)proxy;
		dao2.swim();
	}









动态代理 (JDK代理)

标签:java   proxy   

原文地址:http://lsieun.blog.51cto.com/9210464/1828982

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!