1. 涉及主要jdk api
java.lang.reflect.InvocationHandler;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
public interface InvocationHandler { /** * Processes a method invocation on a proxy instance and returns * the result. This method will be invoked on an invocation handler * when a method is invoked on a proxy instance that it is * associated with. * * @param proxy the proxy instance that the method was invoked on * * @param method theMethod
instance corresponding to * the interface method invoked on the proxy instance. The declaring * class of theMethod
object will be the interface that * the method was declared in, which may be a superinterface of the * proxy interface that the proxy class inherits the method through. * * @param args an array of objects containing the values of the * arguments passed in the method invocation on the proxy instance, * ornull
if interface method takes no arguments. * Arguments of primitive types are wrapped in instances of the * appropriate primitive wrapper class, such as *java.lang.Integer
orjava.lang.Boolean
. * * @return the value to return from the method invocation on the * proxy instance. If the declared return type of the interface * method is a primitive type, then the value returned by * this method must be an instance of the corresponding primitive * wrapper class; otherwise, it must be a type assignable to the * declared return type. If the value returned by this method is *null
and the interface method's return type is * primitive, then aNullPointerException
will be * thrown by the method invocation on the proxy instance. If the * value returned by this method is otherwise not compatible with * the interface method's declared return type as described above, * aClassCastException
will be thrown by the method * invocation on the proxy instance. * * @throws Throwable the exception to throw from the method * invocation on the proxy instance. The exception's type must be * assignable either to any of the exception types declared in the *throws
clause of the interface method or to the * unchecked exception typesjava.lang.RuntimeException
* orjava.lang.Error
. If a checked exception is * thrown by this method that is not assignable to any of the * exception types declared in thethrows
clause of * the interface method, then an * { @link UndeclaredThrowableException} containing the * exception that was thrown by this method will be thrown by the * method invocation on the proxy instance. * * @see UndeclaredThrowableException */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;}
java.lang.reflect.Proxy;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
/* * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */package java.lang.reflect;import java.lang.ref.Reference;import java.lang.ref.WeakReference;import java.security.AccessController;import java.security.Permission;import java.security.PrivilegedAction;import java.util.Arrays;import java.util.Collections;import java.util.HashMap;import java.util.HashSet;import java.util.Map;import java.util.Set;import java.util.WeakHashMap;import sun.misc.ProxyGenerator;import sun.reflect.Reflection;import sun.reflect.misc.ReflectUtil;import sun.security.util.SecurityConstants;/** *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. * *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); ** *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. * * A proxy interface is such an interface that is implemented * by a proxy class. * * A proxy instance is an instance of a proxy class. * * Each proxy instance has an associated invocation handler * object, which implements the interface {
@link InvocationHandler}. * A method invocation on a proxy instance through one of its proxy * interfaces will be dispatched to the { @link InvocationHandler#invoke * invoke} method of the instance's invocation handler, passing the proxy * instance, ajava.lang.reflect.Method
object identifying * the method that was invoked, and an array of typeObject
* containing the arguments. The invocation handler processes the * encoded method invocation as appropriate and the result that it * returns will be returned as the result of the method invocation on * the proxy instance. * *A proxy class has the following properties: * *
- *
- Proxy classes are public, final, and not abstract. * *
- The unqualified name of a proxy class is unspecified. The space * of class names that begin with the string
"$Proxy"
* should be, however, reserved for proxy classes. * * - A proxy class extends
java.lang.reflect.Proxy
. * * - A proxy class implements exactly the interfaces specified at its * creation, in the same order. * *
- If a proxy class implements a non-public interface, then it will * be defined in the same package as that interface. Otherwise, the * package of a proxy class is also unspecified. Note that package * sealing will not prevent a proxy class from being successfully defined * in a particular package at runtime, and neither will classes already * defined by the same class loader and the same package with particular * signers. * *
- Since a proxy class implements all of the interfaces specified at * its creation, invoking
getInterfaces
on its *Class
object will return an array containing the same * list of interfaces (in the order specified at its creation), invoking *getMethods
on itsClass
object will return * an array ofMethod
objects that include all of the * methods in those interfaces, and invokinggetMethod
will * find methods in the proxy interfaces as would be expected. * * - The { @link Proxy#isProxyClass Proxy.isProxyClass} method will * return true if it is passed a proxy class-- a class returned by *
Proxy.getProxyClass
or the class of an object returned by *Proxy.newProxyInstance
-- and false otherwise. * * - The
java.security.ProtectionDomain
of a proxy class * is the same as that of system classes loaded by the bootstrap class * loader, such asjava.lang.Object
, because the code for a * proxy class is generated by trusted system code. This protection * domain will typically be granted *java.security.AllPermission
. * * - Each proxy class has one public constructor that takes one argument, * an implementation of the interface { @link InvocationHandler}, to set * the invocation handler for a proxy instance. Rather than having to use * the reflection API to access the public constructor, a proxy instance * can be also be created by calling the { @link Proxy#newProxyInstance * Proxy.newInstance} method, which combines the actions of calling * { @link Proxy#getProxyClass Proxy.getProxyClass} with invoking the * constructor with an invocation handler. *
A proxy instance has the following properties: * *
- *
- Given a proxy instance
proxy
and one of the * interfaces implemented by its proxy classFoo
, the * following expression will return true: **
* and the following cast operation will succeed (rather than throwing * aproxy instanceof Foo
*ClassCastException
): **
* *(Foo) proxy
* - Each proxy instance has an associated invocation handler, the one * that was passed to its constructor. The static * { @link Proxy#getInvocationHandler Proxy.getInvocationHandler} method * will return the invocation handler associated with the proxy instance * passed as its argument. * *
- An interface method invocation on a proxy instance will be * encoded and dispatched to the invocation handler's { @link * InvocationHandler#invoke invoke} method as described in the * documentation for that method. * *
- An invocation of the
hashCode
, *equals
, ortoString
methods declared in *java.lang.Object
on a proxy instance will be encoded and * dispatched to the invocation handler'sinvoke
method in * the same manner as interface method invocations are encoded and * dispatched, as described above. The declaring class of the *Method
object passed toinvoke
will be *java.lang.Object
. Other public methods of a proxy * instance inherited fromjava.lang.Object
are not * overridden by a proxy class, so invocations of those methods behave * like they do for instances ofjava.lang.Object
. *
Methods Duplicated in Multiple Proxy Interfaces
* *When two or more interfaces of a proxy class contain a method with * the same name and parameter signature, the order of the proxy class's * interfaces becomes significant. When such a duplicate method * is invoked on a proxy instance, the Method
object passed * to the invocation handler will not necessarily be the one whose * declaring class is assignable from the reference type of the interface * that the proxy's method was invoked through. This limitation exists * because the corresponding method implementation in the generated proxy * class cannot determine which interface it was invoked through. * Therefore, when a duplicate method is invoked on a proxy instance, * the Method
object for the method in the foremost interface * that contains the method (either directly or inherited through a * superinterface) in the proxy class's list of interfaces is passed to * the invocation handler's invoke
method, regardless of the * reference type through which the method invocation occurred. * *
If a proxy interface contains a method with the same name and * parameter signature as the hashCode
, equals
, * or toString
methods of java.lang.Object
, * when such a method is invoked on a proxy instance, the * Method
object passed to the invocation handler will have * java.lang.Object
as its declaring class. In other words, * the public, non-final methods of java.lang.Object
* logically precede all of the proxy interfaces for the determination of * which Method
object to pass to the invocation handler. * *
Note also that when a duplicate method is dispatched to an * invocation handler, the invoke
method may only throw * checked exception types that are assignable to one of the exception * types in the throws
clause of the method in all of * the proxy interfaces that it can be invoked through. If the * invoke
method throws a checked exception that is not * assignable to any of the exception types declared by the method in one * of the proxy interfaces that it can be invoked through, then an * unchecked UndeclaredThrowableException
will be thrown by * the invocation on the proxy instance. This restriction means that not * all of the exception types returned by invoking * getExceptionTypes
on the Method
object * passed to the invoke
method can necessarily be thrown * successfully by the invoke
method. * * @author Peter Jones * @version %I%, %E% * @see InvocationHandler * @since 1.3 */public class Proxy implements java.io.Serializable { private static final long serialVersionUID = -2222568056686623797L; /** prefix for all proxy class names */ private final static String proxyClassNamePrefix = "$Proxy"; /** parameter types of a proxy class constructor */ private final static Class[] constructorParams = { InvocationHandler.class }; /** maps a class loader to the proxy class cache for that loader */ private static Map loaderToCache = new WeakHashMap(); /** marks that a particular proxy class is currently being generated */ private static Object pendingGenerationMarker = new Object(); /** next number to use for generation of unique proxy class names */ private static long nextUniqueNumber = 0; private static Object nextUniqueNumberLock = new Object(); /** set of all generated proxy classes, for isProxyClass implementation */ private static Map proxyClasses = Collections.synchronizedMap(new WeakHashMap()); /** * the invocation handler for this proxy instance. * @serial */ protected InvocationHandler h; /** * Prohibits instantiation. */ private Proxy() { } /** * Constructs a new Proxy
instance from a subclass * (typically, a dynamic proxy class) with the specified value * for its invocation handler. * * @param h the invocation handler for this proxy instance */ protected Proxy(InvocationHandler h) { doNewInstanceCheck(); this.h = h; } private static class ProxyAccessHelper { // The permission is implementation specific. static final Permission PROXY_PERMISSION = new ReflectPermission("proxyConstructorNewInstance"); // These system properties are defined to provide a short-term // workaround if customers need to disable the new security checks. static final boolean allowNewInstance; static final boolean allowNullLoader; static { allowNewInstance = getBooleanProperty("sun.reflect.proxy.allowsNewInstance"); allowNullLoader = getBooleanProperty("sun.reflect.proxy.allowsNullLoader"); } private static boolean getBooleanProperty(final String key) { String s = AccessController.doPrivileged(new PrivilegedAction
java.lang.Class
object for a proxy class * given a class loader and an array of interfaces. The proxy class * will be defined by the specified class loader and will implement * all of the supplied interfaces. If a proxy class for the same * permutation of interfaces has already been defined by the class * loader, then the existing proxy class will be returned; otherwise, * a proxy class for those interfaces will be generated dynamically * and defined by the class loader. * * There are several restrictions on the parameters that may be * passed to Proxy.getProxyClass
: * *
- *
- All of the
Class
objects in the *interfaces
array must represent interfaces, not * classes or primitive types. * * - No two elements in the
interfaces
array may * refer to identicalClass
objects. * * - All of the interface types must be visible by name through the * specified class loader. In other words, for class loader *
cl
and every interfacei
, the following * expression must be true: ** Class.forName(i.getName(), false, cl) == i *
* * - All non-public interfaces must be in the same package; * otherwise, it would not be possible for the proxy class to * implement all of the interfaces, regardless of what package it is * defined in. * *
- For any set of member methods of the specified interfaces * that have the same signature: *
- *
- If the return type of any of the methods is a primitive * type or void, then all of the methods must have that same * return type. *
- Otherwise, one of the methods must have a return type that * is assignable to all of the return types of the rest of the * methods. *
- The resulting proxy class must not exceed any limits imposed * on classes by the virtual machine. For example, the VM may limit * the number of interfaces that a class may implement to 65535; in * that case, the size of the
interfaces
array must not * exceed 65535. *
If any of these restrictions are violated, * Proxy.getProxyClass
will throw an * IllegalArgumentException
. If the interfaces
* array argument or any of its elements are null
, a * NullPointerException
will be thrown. * *
Note that the order of the specified proxy interfaces is * significant: two requests for a proxy class with the same combination * of interfaces but in a different order will result in two distinct * proxy classes. * * @param loader the class loader to define the proxy class * @param interfaces the list of interfaces for the proxy class * to implement * @return a proxy class that is defined in 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 getProxyClass
* are violated * @throws NullPointerException if the interfaces
array * argument or any of its elements are null
*/ public static Class
* Proxy.getProxyClass(loader, interfaces). * getConstructor(new Class[] { InvocationHandler.class }). * newInstance(new Object[] { handler }); ** *
Proxy.newProxyInstance
throws * IllegalArgumentException
for the same reasons that * 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 getProxyClass
* are violated * @throws NullPointerException if the interfaces
array * argument or any of its elements are null
, or * if the invocation handler, h
, is * null
*/ public static Object newProxyInstance(ClassLoader loader, Class
2. 例子package test;
import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.util.ArrayList;import java.util.LinkedList;public class AmbiguousTest { //实现 InvocationHandler接口方法invoke class SubInvocationHandler implements InvocationHandler{ private SubProxyInterface
subProxyImpl;//被代理接口 public SubInvocationHandler(SubInvocationHandler subProxyImpl){ this.subProxyImpl = subProxyImpl; }
// proxy 代理类,method:被调用的方法,args:method方法参数 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println(method.getName()); return method.invoke(subProxyImpl, args); } } interface SubProxyInterface{ void getValue(); void get0(); } class SubProxyImpl implements SubProxyInterface{ @Override public void getValue() { System.out.println("-----------------"); } @Override public void get0() { } } public static void main(String[] args) { SubInvocationHandler subInvocationHandler = new AmbiguousTest(). new SubInvocationHandler(new AmbiguousTest().new SubProxyImpl()); Class[] interfaces = new Class[]{SubProxyInterface.class}; //newProxyInstance(加载器,接口数组(被代理接口),invocationhandler对象) Object obj = Proxy.newProxyInstance(SubInvocationHandler.class.getClassLoader() , interfaces,subInvocationHandler); /* 间接写法,是对
Proxy.newProxyInstance的详细调用
try { Object obj0 = Proxy.getProxyClass(SubInvocationHandler.class.getClassLoader() , interfaces).getConstructor(new Class[]{InvocationHandler.class}).newInstance(subInvocationHandler); ((SubProxyInterface)obj0).getValue(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } */ ((SubProxyInterface)obj).getValue(); ((SubProxyInterface)obj).get0(); } }
3.利用反射实现代理,适时利用反射(经典案例:spring aop,ioc)
参考:
public interface InvocationHandler {
/** * Processes a method invocation on a proxy instance and returns * the result. This method will be invoked on an invocation handler * when a method is invoked on a proxy instance that it is * associated with. * * @paramproxy the proxy instance that the method was invoked on * * @parammethod the <code>Method</code> instance corresponding to * the interface method invoked on the proxy instance. The declaring * class of the <code>Method</code> object will be the interface that * the method was declared in, which may be a superinterface of the * proxy interface that the proxy class inherits the method through. * * @paramargs an array of objects containing the values of the * arguments passed in the method invocation on the proxy instance, * or <code>null</code> if interface method takes no arguments. * Arguments of primitive types are wrapped in instances of the * appropriate primitive wrapper class, such as * <code>java.lang.Integer</code> or <code>java.lang.Boolean</code>. * * @returnthe value to return from the method invocation on the * proxy instance. If the declared return type of the interface * method is a primitive type, then the value returned by * this method must be an instance of the corresponding primitive * wrapper class; otherwise, it must be a type assignable to the * declared return type. If the value returned by this method is * <code>null</code> and the interface method's return type is * primitive, then a <code>NullPointerException</code> will be * thrown by the method invocation on the proxy instance. If the * value returned by this method is otherwise not compatible with * the interface method's declared return type as described above, * a <code>ClassCastException</code> will be thrown by the method * invocation on the proxy instance. * * @throwsThrowable the exception to throw from the method * invocation on the proxy instance. The exception's type must be * assignable either to any of the exception types declared in the * <code>throws</code> clause of the interface method or to the * unchecked exception types <code>java.lang.RuntimeException</code> * or <code>java.lang.Error</code>. If a checked exception is * thrown by this method that is not assignable to any of the * exception types declared in the <code>throws</code> clause of * the interface method, then an * {@link UndeclaredThrowableException} containing the * exception that was thrown by this method will be thrown by the * method invocation on the proxy instance. * * @seeUndeclaredThrowableException */ public Object invoke(Object proxy, Method method, Object[] args)throws Throwable;}