Java. Lang. Reflect. Proxy

Source: Internet
Author: User

Package java. Lang. Reflect;

Import java. Lang. Ref .*;
Import java. util .*;

Import sun. Misc. proxygenerator;

/**
* Example of using proxy
*
Interface TT {
String getst ();
}

Class STT implements TT {
Public String getst (){
Return "lqtest ";
}
}

Class myhandler implements invocationhandler {
Tt obj;
 
Public myhandler (tt obj ){
This. OBJ = OBJ;
}
 
Public object invoke (Object proxy, method, object [] ARGs) throws throwable {
System. Out. println ("this is my test ");
Return method. Invoke (OBJ, argS );
}
}

Stt t = new STT ();
Myhandler Hd = new myhandler (t );

TT k = (TT) proxy. newproxyinstance (TT. Class. getclassloader (), new class [] {TT. Class}, HD );
String rtst = K. getst ();

Class proxyclazz = proxy. getproxyclass (TT. Class. getclassloader (), new class [] {TT. Class });
TT k2 = (TT) proxyclazz. getconstructor (new class [] {invocationhandler. Class}). newinstance (new object [] {HD });
String rrst2 = k2.getst ();
* Both methods print strings on the console.
* The agent dynamically generates the class proxyclazz. Although we often load a *. Class file
* Byte arrays that conform to the class file format can also be loaded by classloader. If we are familiar with the class file format,
* We can use a programming method to dynamically generate a class, instead of simply generating a simple proxy class. This capability is not implemented by Sun.
*
* Proxy skills are often used in the AOP technology.
*
* Comment by liqiang
*
* @ Author Peter Jones
*
*/
Public class proxy implements java. Io. serializable {

// Proxy class prefix
Private Final Static string proxyclassnameprefix = "$ proxy ";

// The parameter type of the constructor
Private Final Static class [] constructorparams =
{Invocationhandler. Class };

// Cache corresponding to classloader and proxy class Cache
Private Static map loadertocache = new weakhashmap (3 );

// The identifier of the proxy class being created
Private Static object pendinggenerationmarker = new object ();

// Used to create a unique proxy class name
Private Static long nextuniquenumber = 0;
// The lock used to create the only type of name
Private Static object nextuniquenumberlock = new object ();

// Store all created proxy class objects
Private Static map proxyclasses =
Collections. synchronizedmap (New weakhashmap (3 ));

/**
* The invocation handler for this proxy instance.
* @ Serial
*/
Protected invocationhandler h;

/**
* Prohibits instantiation.
*/
Private proxy (){
}

// Constructor with invocationhandler object as the parameter
Protected proxy (invocationhandler h ){
This. H = h;
}

/**
*
* Dynamically generate proxy classes
* It has the following restrictions:
* 1 each element in the interface array should represent an interface and cannot represent a class or the original type.
* 2 duplicate types are not allowed.
* 3class. forname (I. getname (), false, Cl) = I indicates that the interface can be
* Access
* 4 the two interfaces cannot have the same method name and parameter list but different return values.
* 5 the maximum number of interfaces is 65535
* If the preceding conditions exist, illegalargumentexception is thrown.
* If the array contains null elements, nullpointerexception is thrown.
* Different proxy classes are generated for different interfaces in different order.
*
*
* @ Param loader loads the classloader of this proxy class
* @ Param interfaces interface list
*
*/
Public static class getproxyclass (classloader loader,
Class [] interfaces)
Throws illegalargumentexception
{
// Store dynamically generated class objects
Class proxyclass = NULL;

// Generate stringbuffer for the key value cached by proxy
Stringbuffer keybuffer = new stringbuffer ();

For (INT I = 0; I <interfaces. length; I ++ ){
Class interfaceclass = NULL;

Try {
// Determine whether an interface class object can be obtained by name
Interfaceclass =
Class. forname (interfaces [I]. getname (), false, loader );
} Catch (classnotfoundexception e ){
}

// If the interface class object cannot be obtained by name, an exception is thrown, and interfaceclass is null.
If (interfaceclass! = Interfaces [I]) {
Throw new illegalargumentexception (
Interfaces [I] + "is not visible from Class Loader ");
}

// If the element in the interface array is not an interface, an exception is thrown.
If (! Interfaceclass. isinterface ()){
Throw new illegalargumentexception (
Interfaceclass. getname () + "is not an interface ");
}

// Use ";" to connect to the interface name and generate the cache key
Keybuffer. append (interfaces [I]. getname (). append (';');
}

// Generate the cache key value of string, so that the collection efficiency is not high.
String key = keybuffer. tostring ();

/*
* Find or create the proxy class cache for the class loader.
*/
Map cache;
Synchronized (loadertocache ){
// Obtain the proxy class cache of the corresponding classloader object
Cache = (MAP) loadertocache. Get (loader );

If (Cache = NULL ){
// If there is no cache corresponding to this classloader, create it
Cache = new hashmap (3 );
Loadertocache. Put (loader, cache );
}

// The subsequent part of this method, loadertocache, is still valid, but not synchronized because
// Mapping is removed only when the loader cannot be touched in a timely manner.
}

// Use the string key value to find the proxy class. There are three possible cases:
// 1 if the current cache does not have this proxy class, null is returned.
// 2 If the proxy class is being created, the pendinggenerationmarker object is returned.
// 3 if the proxy class has been created, the weakreference object is returned.
Synchronized (cache ){
/*
* Note that we need not worry about reaping the cache
* Entries with cleared weak references because if a proxy class
* Has been garbage collected, its class loader will have been
* Garbage collected as well, so the entire cache will be reaped
* From the loadertocache map.
*/
Do {
// Retrieve the reference object that encapsulates the proxy class object through the interface list key value
Object value = cache. Get (key );
If (value instanceof reference ){
// Retrieve the proxy class object from the reference object
Proxyclass = (class) (reference) value). Get ();
}

If (proxyclass! = NULL ){
// If the proxy class object has been created, return directly
Return proxyclass;
} Else if (value = pendinggenerationmarker ){
// Wait if the proxy object is being created
Try {
Cache. Wait ();
} Catch (interruptedexception e ){
// The process of creating a class is short and set to a long time. Therefore, the interrupt processing is ignored here.
}

// If the proxy is created or interrupted, the proxy class object in the cache will continue to be obtained through the key value.
Continue;
} Else {
// If it is not created, it indicates that it is being created
Cache. Put (Key, pendinggenerationmarker );
// Jump out of the loop and create this proxy class
Break;
}
} While (true );
}

Try {
// Proxy class package
String proxypkg = NULL;

/*
* Record the package of a non-public proxy interface so that
* Proxy class will be defined in the same package. Verify that
* All non-public proxy interfaces are in the same package.
*/
For (INT I = 0; I <interfaces. length; I ++ ){
// Obtain the descriptor of each interface
Int flags = interfaces [I]. getmodifiers ();

If (! Modifier. ispublic (flags) {// not common
String name = interfaces [I]. getname ();
Int n = Name. lastindexof ('.');
// Get the package name. If there is no package name, use a Null String
String PKG = (n =-1 )? "": Name. substring (0, n + 1 ));

If (proxypkg = NULL) {// The first Interface
Proxypkg = PKG;
} Else if (! PKG. Equals (proxypkg )){
// If the interface is not public and is not in the same package, an exception is thrown.
Throw new illegalargumentexception (
"Non-public interfaces from different packages ");
}
}

}

If (proxypkg = NULL) {// if there is no non-public interface
Proxypkg = ""; // use an anonymous package
}

// A block is used.
{
/*
* Choose a name for the proxy class to generate.
*/
Long num;
Synchronized (nextuniquenumberlock ){
// Static attributes are used as locks to protect data in the synchronization area.
// Because num is of the long type, the original object cannot be locked (only the class can be locked)
// Performance will be wasted if the entire object is locked
// Use a lock object to protect Multiple Data (objects, original types) at the same time

Num = nextuniquenumber ++;
}

// Spell out a new class name. the spelling of the class name is the package name + $ proxy + unique long value.
String proxyname = proxypkg + proxyclassnameprefix + num;

// Generate the class bytecode
Byte [] proxyclassfile = proxygenerator. generateproxyclass (
Proxyname, interfaces );

Try {
// Load this class
Proxyclass = defineclass0 (loader, proxyname,
Proxyclassfile, 0, proxyclassfile. Length );
} Catch (classformaterror e ){
Throw new illegalargumentexception (E. tostring ());
}
}

// Place the newly created Class Object to the set that stores the Class Object of the created proxy class
Proxyclasses. Put (proxyclass, null );

} Finally {
Synchronized (cache ){
If (proxyclass! = NULL ){
// If it is successfully created, the value in the cache will be reset. It turns out to be pendinggenerationmarker.
Cache. Put (Key, new weakreference (proxyclass ));
} Else {
// If creation fails, the corresponding key is deleted.
Cache. Remove (key );
}

// Wake up all pending processes because they encounter a proxy class being created
Cache. policyall ();
}
}
 
Return proxyclass;
}

/**
* Quick method for creating a proxy object
*
* @ Param loader loads the classloader of this proxy class
* @ Param interfaces interface list
* @ Param H invocationhandler object
*
*/
Public static object newproxyinstance (classloader loader,
Class [] interfaces,
Invocationhandler H)
Throws illegalargumentexception
{
If (H = NULL ){
// If invocationhandler is null, an exception is thrown.
Throw new nullpointerexception ();
}

// Obtain the proxy class
Class Cl = getproxyclass (loader, interfaces );

Try {
// Obtain the constructor with an invocationhandler object parameter
Constructor cons = Cl. getconstructor (constructorparams );
// Create an instance
Return (object) cons. newinstance (new object [] {H });
} Catch (nosuchmethodexception e ){
Throw new internalerror (E. tostring ());
} Catch (illegalaccessexception e ){
Throw new internalerror (E. tostring ());
} Catch (instantiationexception e ){
Throw new internalerror (E. tostring ());
} Catch (invocationtargetexception e ){
Throw new internalerror (E. tostring ());
}
}

// Determine whether the specified class is created
Public static Boolean isproxyclass (class Cl ){
If (CL = NULL ){
Throw new nullpointerexception ();
}

Return proxyclasses. containskey (CL );
}

// If proxy is a proxy object, get its getinvocationhandler object; otherwise, an exception is thrown.
Public static invocationhandler getinvocationhandler (Object proxy)
Throws illegalargumentexception
{
// Check whether the proxy object is an object of the generated proxy class.
If (! Isproxyclass (proxy. getclass ())){
Throw new illegalargumentexception ("not a proxy instance ");
}

// If yes, transition
Proxy P = (proxy) proxy;
Return p. h;
}

// Load the local method of the class
Private Static native class defineclass0 (classloader loader, string name,
Byte [] B, int off, int Len );
}

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.