Java Dynamic proxy Internal Mechanism

Source: Internet
Author: User
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:

ProxyProvides 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 toinvokeMethod of the Instance's invocation handler, passing the proxy instance,java.lang.reflect.MethodObject identifying the Method
That was invoked, and an array of TypeObjectContaining 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 extendsjava.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, invokinggetInterfacesON ITSClassObject will return an array containing the same list of interfaces (in the order specified at its creation), invokinggetMethods
    ON ITSClassObject will return an arrayMethodObjects that include all of the methods in those interfaces, and invokinggetMethodWill find methods in the proxy interfaces as wocould be expected.
  • TheProxy.isProxyClassMethod will return true if it is passed a proxy class -- a class returnedProxy.getProxyClassOr the class of an object returnedProxy.newProxyInstance-- And false otherwise.
  • Thejava.security.ProtectionDomainOf 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 interfaceInvocationHandler, 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.newInstanceMethod, which combines the actions of callingProxy.getProxyClassWith invoking the constructor with an invocation
    Handler.

A proxy instance has the following properties:

  • Given a proxy instanceproxyAnd one of the interfaces implemented by its proxy classFoo, The following expression will return true:

         proxy instanceof Foo 

    And the following cast operation will succeed (rather than throwingClassCastException):

         (Foo) proxy 
  • Each proxy instance has an associated invocation handler, the one that was passed to its constructor. The staticProxy.getInvocationHandlerMethod will return the invocation handler associated with the proxy instance passed
    Its argument.
  • An Interface Method Invocation on a proxy instance will be encoded and dispatched to the invocation handler'sinvokeMethod as described in the documentation for that method.
  • An invocation ofhashCode,equals, OrtoStringMethods declared injava.lang.ObjectOn a proxy instance will be encoded and dispatched to the invocation handler'sinvokeMethod in the same
    Manner as interface method invocations are encoded and dispatched, as described abve. The declaring class ofMethodObject passedinvokeWill bejava.lang.Object. Other public methods of a proxy instance inherited
    Fromjava.lang.ObjectAre not overridden by a proxy class, so invocations of those methods behave like they do for instancesjava.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 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,MethodObject 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'sinvokeMethod, 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, OrtoStringMethodsjava.lang.Object, When such a method is invoked on a proxy instance,Method
Object passed to the invocation handler will havejava.lang.ObjectAs its declaring class. In other words, the public, non-final methodsjava.lang.ObjectLogically 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,invokeMethod may only throw checked exception types that are assignable to one of the exception types inthrowsClause of the method inAll
Of the proxy interfaces that it can be invoked through. IfinvokeMethod 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 uncheckedUndeclaredThrowableExceptionWill be thrown by the invocation on the proxy instance. This restriction means that not all of the exception types returned by invokinggetExceptionTypesOnMethodObject passed
ToinvokeMethod can necessarily be thrown successfully byinvokeMethod.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.