Lazy Loading from Java Reflection (proxy mode) (ii)

Source: Internet
Author: User

Proxy mode

Proxy mode uses proxy objects to complete user requests, shielding users from access to real objects. The real-world agent is authorized to perform some matters of the parties without the parties appearing, from the perspective of a third party, it seems that the parties do not exist, because he only communicates with the agent. In fact, the agent is to have the authorization of the Parties, and in the core issue also need to consult the parties.

In software design, the use of proxy mode is also a lot of intent, such as for security reasons need to shield the client directly access real objects, or in remote calls need to use the proxy class to handle the technical details of the remote method call (such as RMI), may also be to improve system performance, the real object is encapsulated, To achieve the purpose of lazy loading.

The proxy mode role is divided into 4 types:

  1. Topic Interface: The public external method of defining the proxy class and the real topic, as well as the method of the real topic of proxy class agent;

  2. Real topic: Classes that truly implement business logic;

  3. Proxy class: Used to proxy and encapsulate real topics;

  4. Main: The client, using the proxy class and the topic interface to do some work.

Back to top of page

Lazy Loading

A simple example illustrates the method of using proxy mode to implement lazy loading and its significance. It is assumed that a client software has the ability to query data based on user requests to the database. Before querying the data, you need to get a database connection, initialize all classes of the system when the software is on, and try to get a database connection. When there are a large number of similar operations in the system (such as XML parsing, etc.), all of these initialization operations are superimposed so that the system starts very slowly. To do this, the proxy class using proxy mode encapsulates the initialization of the database query, and when the system starts, initializes the proxy class rather than the real database query class, and the proxy class does nothing. Therefore, its structure is quite rapid.

When the system starts, the most resource-consuming methods are separated using the proxy mode, which can speed up the system startup and reduce the user's waiting time. And when the user actually does the query operation, then the proxy class will load the real database query class separately, complete the user's request. This is the process of using proxy mode to implement lazy loading.

The central idea of lazy loading is that if you do not use this component at this time, you do not need to really initialize it, use a proxy object instead of its original location, and load it only when it is really needed. Lazy loading using proxy mode is very meaningful, first of all, it can spread the system pressure on the timeline, especially when the system starts, does not have to complete all the initialization work, thereby speeding up the start-up time, and secondly, for many real topics, in the software startup until the shutdown of the entire process, may not be called at all, Initializing these data is undoubtedly a waste of resources. For example, using a proxy class to encapsulate a database query class, the system starts the process as an example. If the system does not use proxy mode, the Dbquery object is initialized at startup, and when the proxy mode is used, only a lightweight object dbqueryproxy should be initialized at startup.

The following code idbquery is the topic interface, which defines the services that the proxy class and the real class need to provide externally, and defines the public method request () function that implements the database query. Dbquery is the real topic, responsible for the actual business operations, Dbqueryproxy is Dbquery proxy class.

Listing 1. Deferred Load Agent
Public interface Idbquery {String request (), public class Dbquery implements idbquery{public Dbquery () {try{Thread.sle EP (1000);//Assume a time-consuming operation such as database connection}catch (Interruptedexception ex) {ex.printstacktrace ();}}  @Overridepublic string Request () {//TODO auto-generated method Stubreturn "request string";} } public class Dbqueryproxy implements idbquery{private dbquery real = null; @Overridepublic String request () {//TODO Au To-generated method stub//creates a real object when it is really needed, and the creation process can be slow if (real==null) {real = new dbquery ();} In a multithreaded environment, this returns a dummy class, similar to the future mode return Real.request ();} } public class Main {public static void main (string[] args) {idbquery q = new Dbqueryproxy ();//use of q.request ();//in the real use Subset create a Real object}}

Back to top of page

Dynamic Agent

Dynamic proxies are dynamically generated proxy classes at run time. That is, the byte code of the proxy class is generated at run time and loaded into the current proxy's ClassLoader. Dynamic classes have many benefits compared to static processing classes. First of all, there is no need to write a formal package for the real topic, if there are many methods in the topic interface, it is troublesome to write an agent method for each interface. If the interface changes, then the real topic and proxy classes are modified, not conducive to system maintenance, and secondly, the use of some dynamic proxy generation method can even develop the execution logic of the proxy class at runtime, thus greatly improving the system flexibility.

Dynamic proxy classes use bytecode to dynamically generate loading techniques that generate load classes at run time. There are many ways to generate dynamic proxy classes, such as the dynamic processing, CGLIB, Javassist, or ASM libraries that the JDK comes with. The JDK's dynamic proxy is simple to use, it is built into the JDK, so there is no need to introduce a third-party Jar package, but the relative functionality is relatively weak. Both CGLIB and Javassist are high-level bytecode generation libraries, and the overall performance is better than the dynamic proxy that comes with the JDK, and it's very powerful. ASM is a low-level bytecode generation tool that uses ASM that is almost always programmed with Java bytecode, the most demanding developer, and, of course, a dynamic agent generation tool with the best performance. However, the use of ASM is cumbersome, and performance is not an order of magnitude improvement, and CGLIB and other advanced bytecode generation tools compared to the maintenance of the ASM program is poor, if not in the performance of the requirements of the occasion, or recommend CGLIB or Javassist.

As an example of Dbqueryproxy in the code shown in Listing 1, use dynamic proxies to generate dynamic classes, replacing the dbqueryproxy in the previous example. First, the proxy object is generated using the JDK's dynamic agent. The dynamic agent of the JDK needs to implement the Handler of a processing method call to implement the internal logic of the proxy method.

Listing 2. Dynamic Agent
Import Java.lang.reflect.invocationhandler;import Java.lang.reflect.method;public class Dbqueryhandler implements Invocationhandler{idbquery Realquery = null;//defines the theme interface @overridepublic object Invoke (Object proxy, method, object[] args) throws Throwable {//TODO auto-generated method stub//If first call, generate true subject if (Realquery = = null) {realquery = new dbquery (); }//return to the real topic to complete the actual operation return Realquery.request ();} }

The above code implements a Handler, and it can be seen that its internal logic and dbqueryproxy are similar. Try to generate a real topic object before calling the method of the real topic. Next, you need to use this Handler to generate a dynamic proxy object. The code is shown in Listing 3.

Listing 3. Generating dynamic proxy objects
import Java.lang.reflect.invocationhandler;import Java.lang.reflect.method;import Java.lang.reflect.proxy;public class Dbqueryhandler implements InvocationHandler{ Idbquery Realquery = null;//defines the theme interface @overridepublic object Invoke (Object proxy, method, object[] args) throws Throwab Le {//TODO auto-generated method stub//If first called, generates true subject if (Realquery = = null) {realquery = new dbquery ();} Return to real topic complete the actual operation return Realquery.request ();} public static Idbquery Createproxy () {Idbquery proxy = (idbquery) proxy.newproxyinstance ( Classloader.getsystemclassloader (), New Class[]{idbquery.class}, New Dbqueryhandler ()); return proxy;} }

The code above generates a proxy class that implements the Idbquery interface, and the internal logic of the proxy class is determined by Dbqueryhandler. After the proxy class is generated, an instance of the proxy class is returned by the Newproxyinstance () method. At this point, a complete dynamic agent is completed.

In Java, the generation of dynamic proxy classes mainly involves the use of ClassLoader. Taking CGLIB as an example, using CGLIB to generate a dynamic proxy, you first need to generate an instance of the enhancer class and specify the callback class to handle the proxy business. In the Enhancer.create () method, the byte code of the dynamic proxy class is generated using the Defaultgeneratorstrategy.generate () method and saved in a byte array. Then, using the Reflectutils.defineclass () method, the byte code is loaded into the ClassLoader through reflection, calling the Classloader.defineclass () method, and completing the class loading. Finally, using the Reflectutils.newinstance () method, the instance of the dynamic class is generated by reflection, and the instance is returned. The basic process is to generate a class bytecode based on the specified callback class-The bytecode is defined as a class by DefineClass ()-The instance of the class is generated using the reflection mechanism. The complete process of generating a class using CGLIB dynamic reflection is shown in Listing 4 through listing 7.

Listing 4. Defining interfaces
Public interface Bookproxy {public void Addbook ();}
Listing 5. Defining implementation Classes
The class does not state the Bookproxy interface public class Bookproxyimpl {public void Addbook () {System.out.println ("common method for adding books ...");}  }
Listing 6. Defining reflection classes and overloaded methods
Import Java.lang.reflect.Method; Import Net.sf.cglib.proxy.Enhancer; Import Net.sf.cglib.proxy.MethodInterceptor; Import Net.sf.cglib.proxy.MethodProxy; public class Bookproxylib implements Methodinterceptor {private object target;/** * Create proxy Object * * @param target * @retur  n */Public Object getinstance (object target) {this.target = target;  Enhancer enhancer = new enhancer ();  Enhancer.setsuperclass (This.target.getClass ());  Callback method Enhancer.setcallback (this); Create proxy object return Enhancer.create (); } @Override//callback method public Object intercept (object obj, Method method, object[] args, Methodproxy proxy) throws Throwabl  e {System.out.println ("things start");  Proxy.invokesuper (obj, args);  System.out.println ("End of Thing"); return null; } }
Listing 7. Run the program
public class Testcglib {public  static void Main (string[] args) {  bookproxylib cglib=new bookproxylib ();  Bookproxyimpl bookcglib= (Bookproxyimpl) cglib.getinstance (New Bookproxyimpl ());  Bookcglib.addbook ();  } }
Listing 8. Run output
The general way things start to increase books ... The end of Things

Back to top of page

Application of proxy mode

There are several applications for proxy mode, as described below:

  1. A remote proxy, which provides a local representation of an object in a different address space, hides the fact that an object exists in a different address space. For example, WebService, when we add a Web reference to the application's project, reference a WebService, it will be in the project to claim a webreference folder and some files, this is a proxy role, This allows the client program to invoke the agent to resolve the remote access problem;

  2. A virtual agent is an expensive object that is created as needed to hold real objects that take a long time to instantiate. This can achieve performance optimization, such as open a Web page, the page contains a lot of text and pictures, but we can quickly see the text, but the picture is a piece of the underground to see, those not open picture frame, is through the virtual generation to replace the real picture, At this time the agent stores the path and size of the real picture;

  3. A security agent that controls access to real objects. Generally used when the object should have different access rights;

  4. Pointer reference refers to the agent handling other things when the real object is called. For example, count the number of references to a real object, so that when the object has no references, it can be automatically freed, or when a persistent object is first referenced, it is loaded into memory, or if it has been freed before accessing an actual object, to ensure that other objects cannot change it. These are handled by the agent when accessing an object by attaching some housekeeping;

  5. Lazy loading, a classic application that uses proxy mode for lazy loading is inside the Hibernate framework. When Hibernate loads an entity bean, it does not load all of the database data at once. By default, it takes the mechanism of lazy loading to improve the performance of the system. Lazy loading in Hibernate is mainly divided into two classes: deferred loading of attributes and delayed loading of associated tables. The implementation principle is to use the agent to intercept the original getter method, in the real use of object data only to the database or other third-party components to load the actual data, thereby improving system performance.


Lazy Loading from Java Reflection (proxy mode) (ii)

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.