Document directory
- Methods duplicated in multiple proxy Interfaces
The important class is proxy. First, you must understand the reflection mechanism!
Spring AOP is a dynamic proxy mechanism.
Import Java. lang. reflect. constructor; import Java. lang. reflect. invocationhandler; import Java. lang. reflect. method; import Java. lang. reflect. proxy; import Java. util. collection; public class demo {public static void main (string [] ARGs) throws throwable {// collection is a Java Collection Interface Class clazzproxy1 = proxy. getproxyclass (collection. class. getclassloader (), collection. class); // print the result as $ proxy0system. out. println (clazz Proxy1.getname (); system. out. println ("----------- constructor [] constructors = clazzproxy1.getconstructors (); For (constructor con: constructors) {string name = con. getname (); stringbuilder sbuilder = new stringbuilder (name); sbuilder. append ('); Class [] clazzparams = con. getparametertypes (); For (Class C: clazzparams) sbuilder. append (C. getname ()). append (""); sbuilder. append ('); system. out. Println (sbuilder);} method [] Methods = clazzproxy1.getmethods (); system. out. println ("----------- method list start ---------"); stringbuilder sbuilder = new stringbuilder (); For (method M: Methods) {sbuilder. append (M. getname (); Class clazzparameters [] = m. getparametertypes (); For (class para: clazzparameters) sbuilder. append ('('). append (para. getname ()). append ('); sbuilder. append ('\ n');} system. out. println (sbuilder); syst Em. Out. println ("-------- object creation start --------"); constructor = clazzproxy1.getconstructor (invocationhandler. Class); // The constructor receives the invocationhandler interface type. We need an instance class myinvocationhandler implements invocationhandler for this interface {// here, nothing is written here @ overridepublic object invoke (Object proxy, method, object [] ARGs) throws throwable {return NULL;} collection proxy1 = (Collection) constructor. newinstance (New myinvocationhandler (); system. out. println (proxy1); // The result is null. because proxy1.tostring () is null, rather than proxy1 is null, see the following description: proxy1.clear (); // executable // proxy1.size (); // Error !!}}
If the last line is commented out, an error will occur during the operation. If a method with a return value is called, an error will occur! The cause is explained later.
Print result:
$ Proxy0 ----------- start of the constructor --------- $ proxy0 (Java. lang. reflect. invocationhandler,) ----------- method list start --------- add (Java. lang. object) hashcodeclearequals (Java. lang. object) tostringcontains (Java. lang. object) isemptyaddall (Java. util. collection) iteratorsizetoarray ([ljava. lang. object;) toarrayremove (Java. lang. object) containsall (Java. util. collection) removeall (Java. util. collection) retainall (Java. util. collection) isproxyclass (Java. lang. class) getproxyclass (Java. lang. classloader) ([ljava. lang. class;) getinvocationhandler (Java. lang. object) newproxyinstance (Java. lang. classloader) ([ljava. lang. class;) (Java. lang. reflect. invocationhandler) waitwait (long) (INT) Wait (long) getclassnotifypolicyall -------- object creation start -------- null
Simplify the preceding writing (anonymous internal class ):
Collection proxy2 = (Collection)Proxy.newProxyInstance(Collection.class.getClassLoader(),new Class[]{Collection.class}, new InvocationHandler() {public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {return null;}});
Then add some actual operations: (here we can filter the ARGs parameters, that is, modify the input parameters .)
Here, an arryalist is added because it implements the collection interface!
Collection proxy2 = (Collection)Proxy.newProxyInstance(Collection.class.getClassLoader(),new Class[]{Collection.class}, new InvocationHandler() {ArrayList target = new ArrayList();public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {return method.invoke(target, args);}});proxy2.add(1);proxy2.add(2);System.out.println(proxy2.size());
Analysis:
1. The dynamically generated class implements the collection interface (several interfaces can be implemented). The generated class includes all the methods in the collection interface and a constructor that receives the invocationhandler parameter.
2. the constructor receives an invocationhandler object.
Internal Implementation Mechanism (overview ):
$ Proxy0 implemets collection {
Invocationhandler handler;
Public $ proxy0 (invocationhadler hander ){
This. Handler = handler;
}
// Methods inherited from the interface call handler. Invoke ()
// The three methods including hashcode (0 tostring () equals () inherited from the object will be delegated to handler for execution.
Int size (){
Return handler. Invoke (this, this. getclass (). getmethod ("size"), null );
}
Void clear (){
Handler. Invoke (this, this. getclass (). getmethod ("clear"), null );
}
}
Analyze the errors in the first code:
The size () method requires the return value, while our hanler. Invoke () returns NULL.
System. out. println (proxy1); // The result is null. because proxy1.tostring () is also called by hanler. invoke (), printing is null, not to say proxy1 itself is null
Official introduction:
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 InterfaceFoo
:
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);
ADynamic proxy class(Simply referred to asProxy classBelow) is a class that implements a list of interfaces specified at runtime when the class is created, with behavior as described below.Proxy InterfaceIs such an Interface
That is implemented by a proxy class.Proxy instanceIs an instance of a proxy class. Each proxy instance has an associatedInvocation HandlerObject, which implements the interfaceInvocationHandler
. A Method Invocation
On a proxy instance through one of its proxy interfaces will be dispatched toinvoke
Method of the Instance's invocation handler, passing the proxy instance,java.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
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"
Shocould 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 particle package at runtime, and neither will classes already defined by the same class loader and the same package with the particle signers.
- Since a proxy class implements all of the interfaces specified at its creation, invoking
getInterfaces
ON ITSClass
Object will return an array containing the same list of interfaces (in the order specified at its creation), invokinggetMethods
ON ITSClass
Object will return an arrayMethod
Objects that include all of the methods in those interfaces, and invokinggetMethod
Will find methods in the proxy interfaces as wocould be expected.
- The
Proxy.isProxyClass
Method will return true if it is passed a proxy class -- a class returnedProxy.getProxyClass
Or the class of an object returnedProxy.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, suchjava.lang.Object
, Because the code for a proxy class is generated by trusted system code. This
Protection domain will typically be grantedjava.security.AllPermission
.
- Each proxy class has one public constructor that takes one argument, an implementation of the interface
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 callingProxy.newInstance
Method, which combines the actions of callingProxy.getProxyClass
With invoking the constructor with an invocation
Handler.
A proxy instance has the following properties:
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 suchDuplicate MethodIs invoked on a proxy instance,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,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'sinvoke
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 ashashCode
,equals
, OrtoString
Methodsjava.lang.Object
, When such a method is invoked on a proxy instance,Method
Object passed to the invocation handler will havejava.lang.Object
As its declaring class. In other words, the public, non-final methodsjava.lang.Object
Logically precede all of the proxy interfaces for the determination of whichMethod
Object To pass to the invocation handler.
Note also that when a duplicate method is dispatched to an invocation handler,invoke
Method may only throw checked exception types that are assignable to one of the exception types inthrows
Clause of the method inAll
Of the proxy interfaces that it can be invoked through. Ifinvoke
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 uncheckedUndeclaredThrowableException
Will be thrown by the invocation on the proxy instance. This restriction means that not all of the exception types returned by invokinggetExceptionTypes
OnMethod
Object passed
Toinvoke
Method can necessarily be thrown successfully byinvoke
Method.