JAVA design mode-proxy Mode

Source: Internet
Author: User

JAVA design mode-proxy Mode
Proxy Mode

Proxy mode uses a proxy object to complete user requests, Shielding users from accessing real objects. In the real world, the agent is authorized to execute some matters of the client. The client does not need to come forward. From the perspective of a third party, it seems that the client does not exist because he only communicates with the agent. In fact, the agent must have the authorization of the client and request the client for instructions on core issues.

In software design, there are many intentions to use the proxy mode. For example, for security reasons, you need to shield the client from directly accessing the real object, or technical details (such as RMI) that require the proxy class to process remote method calls in remote calls may also be encapsulated to improve system performance, so as to achieve delayed loading.
There are four types of proxy mode roles:

Topic interface: defines the public external methods of proxy classes and real themes. It is also the method of real themes of proxy classes: classes that truly implement business logic; proxy classes: Used to proxy and encapsulate real themes; main: client. Use the proxy class and topic interface to complete some work. Delayed Loading

A simple example is provided to illustrate the method and significance of using the proxy mode to implement delayed loading. Assume that a client software can query data in the database according to user requests. Before querying data, you need to obtain the database connection. When the software is enabled, all classes of the system are initialized, and the database connection is attempted. When the system has a large number of similar operations (such as XML parsing), the superposition of all these initialization operations will make the system startup very slow. Therefore, the proxy class is used to encapsulate initialization operations for database queries. When the system starts, the proxy class is initialized, not the real database query class, but the proxy class does nothing. Therefore, its structure is quite rapid.

When the system is started, the methods that consume the most resources are separated using the proxy mode, which can speed up the system startup and reduce user waiting time. When a user performs a query operation, the proxy class independently loads the real Database Query Class to complete the user's request. In this process, the agent mode is used to implement delayed loading.

The core idea of delayed loading is: if this component is not currently used, you do not need to initialize it and use a proxy object to replace its original location, you only need to load it as needed. It is very meaningful to use the delayed Loading Mode in proxy mode. First, it can distribute the system pressure on the timeline, especially when the system is started, so that you do not have to complete all initialization work to accelerate the startup time; second, for many real theme, the whole process of software startup till it is closed may not be called at all, and initialization of such data is undoubtedly a waste of resources. For example, the system startup process is used to encapsulate the Database Query Class Using the proxy class. If the system does not use the proxy mode, DBQuery objects will be initialized at startup. After using the proxy mode, you only need to initialize a lightweight object DBQueryProxy at startup.
The following code uses IDBQuery as the topic interface. It defines the services to be provided by the proxy class and the real class, and defines the public Method request () function to implement database query. DBQuery is a real topic and is responsible for actual business operations. DBQueryProxy is the proxy class of DBQuery.
Listing 1. Delayed loading proxy

Public interface IDBQuery {String request ();} public class DBQuery implements IDBQuery {public DBQuery () {try {Thread. sleep (1000); // assume time-consuming operations such as database connection} catch (InterruptedException ex) {ex. printStackTrace () ;}@ Override public String request () {// TODO Auto-generated method stub return "request string ";}} public class DBQueryProxy implements IDBQuery {private DBQuery real = null; @ Override public String request () {// TODO Auto-generated method stub // you can create real objects only when necessary, the creation process may be slow. if (real = null) {real = new DBQuery ();} // in a multi-threaded environment, a false class is returned, similar to the Future mode return real. request () ;}} public class Main {public static void main (String [] args) {IDBQuery q = new DBQueryProxy (); // use q. request (); // create a real object only when actually used }}
Dynamic proxy

Dynamic proxy refers to the dynamic generation of proxy classes at runtime. That is, the byte code of the proxy class will be generated and loaded into the ClassLoader of the current proxy at runtime. Compared with the static processing class, the dynamic class has many advantages. First, you do not need to write a fully identical encapsulation class for a real topic. If there are many methods in the topic interface, it is also very troublesome to write a proxy method for each interface. If the interface changes, the real subject and proxy class must be modified, which is not conducive to system maintenance. Second, the execution logic of the proxy class can be developed at runtime by using dynamic proxy generation methods, this greatly improves the system flexibility.

Dynamic proxy classes use bytecode dynamic generation and loading technology to generate loading classes at runtime. There are many ways to generate a dynamic proxy class, such as the built-in dynamic processing, CGLIB, Javassist, or ASM library of JDK. The dynamic proxy of JDK is easy to use and built-in in JDK. Therefore, third-party Jar packages are not required, but the functions are relatively weak. CGLIB and ipvsist are both advanced bytecode generation libraries. The overall performance is better than the built-in dynamic proxy of JDK, and the functions are very powerful. ASM is a low-level bytecode generation tool. It is almost the same as using Java bytecode for programming. It has the highest requirements for developers. Of course, it is also the best dynamic proxy generation tool. However, the use of ASM is cumbersome and its performance has not been improved by an order of magnitude. Compared with advanced bytecode generation tools such as CGLIB, the ASM Program has poor maintainability, CGLIB or Javassist is recommended if you are not demanding performance.

Take DBQueryProxy in the code shown in Listing 1 as an example. Use Dynamic proxy to generate dynamic classes and replace DBQueryProxy in the previous example. First, use the dynamic proxy of JDK to generate a proxy object. JDK's dynamic proxy needs to implement a Handler to call the processing method, which is used to implement the internal logic of the proxy method.

List 2. Dynamic proxy
Import java. lang. reflect. InvocationHandler;
Import java. lang. reflect. Method;

Public class DBQueryHandler implements InvocationHandler {IDBQuery realQuery = null; // defines the topic interface @ Override public Object invoke (Object proxy, Method method, Object [] args) throws Throwable {// TODO Auto-generated method stub // if the first call is made, generate the real topic if (realQuery = null) {realQuery = new DBQuery ();} // return the real theme to complete the actual operation return realQuery. request ();}}

The above code implements a Handler. We can see that its internal logic is similar to that of DBQueryProxy. Try to generate a real theme object before calling the real theme method. Then, use the 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 topic interface @ Override public Object invoke (Object proxy, Method method, Object [] args) throws Throwable {// TODO Auto-generated method stub // if the first call is made, generate the real topic if (realQuery = null) {realQuery = new DBQuery ();} // return the real theme to 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. The internal logic of the proxy class is determined by DBQueryHandler. After a proxy class is generated, the newProxyInstance () method returns an instance of the proxy class. So far, a complete dynamic proxy is complete.

In Java, the generation of dynamic proxy classes mainly involves the use of ClassLoader. Take CGLIB as an example. To use CGLIB to generate a dynamic proxy, you must first generate an Enhancer class instance and specify a callback class for processing proxy services. In the Enhancer. create () method, the ultgeneratorstrategy. Generate () method is used to Generate the bytecode of the dynamic proxy class and save it in the byte array. Then, use the ReflectUtils. defineClass () method and call the ClassLoader. defineClass () method through reflection to load the bytecode into the ClassLoader to load the class. Finally, use the ReflectUtils. newInstance () method to generate a dynamic class instance through reflection and return the instance. The basic process is to generate a Class bytecode Based on the specified callback Class-define the bytecode as a Class through defineClass ()-use the reflection mechanism to generate an instance of this Class. The entire process from listing 4 to listing 7 is to use cglib dynamic reflection to generate classes.

Listing 4. Defining Interfaces
public interface BookProxy {public void addBook();}

Listing 5. defining implementation classes

// This class does not declare the BookProxy interface public class BookProxyImpl {public void addBook () {System. out. println ("add a normal method of books ...");}}

Listing 6. Defining reflection classes and overload 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 * @ return */public Object getInstance (Object target) {this.tar get = target; Enhancer enhancer = new Enhancer (); enhancer.setSuperclass(this.tar get. getClass (); // callback method enhancer. setCallback (this); // create the proxy object return enhancer. create () ;}@ Override // callback Method public Object intercept (Object obj, method Method, Object [] args, MethodProxy proxy) throws Throwable {System. out. println ("transaction start"); proxy. invokeSuper (obj, args); System. out. println ("transaction end"); 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. Running output
Transaction start
Add a normal method for books...
Transaction end

Proxy Mode Applications
The proxy mode has multiple application scenarios, as described below:

Remote proxy provides a local representation of an object in different address spaces, which can hide the fact that an object exists in different address spaces. For example, if we add a Web reference to an application project and reference a WebService, A WebReference folder and some files will be claimed in the project, this is acting as a proxy, so that the client can call the proxy to solve the remote access problem;

A virtual proxy is used to create objects with high overhead as needed to store real objects that take a long time for instantiation. In this way, the performance can be optimized. For example, when a webpage is opened, the webpage contains a large amount of text and images, but we can quickly see the text, however, images can only be seen after being downloaded one by one. The unopened image boxes are replaced by the virtual proxy. At this time, the proxy stores the path and size of the real image;

Security Proxy, used to control the access permissions of real objects. It is generally used when the object should have different access permissions;

Pointer Reference refers to the proxy to handle other things when calling a real object. For example, you can calculate the number of references of a real object. In this way, when the object is not referenced, it can be automatically released, or when a persistent object is referenced for the first time, it is loaded into the memory, or, before accessing an actual object, check whether it has been released to ensure that other objects cannot change it. These are all added with housekeeping when accessing an object through a proxy;

Delayed loading: a classic application that uses the proxy mode to implement delayed loading is in The Hibernate framework. When Hibernate loads the object bean, it does not load all the data in the database at one time. By default, it uses a delayed loading mechanism to improve system performance. Delayed loading in Hibernate is mainly divided into two types: delayed loading of attributes and delayed loading of associated tables. The principle is to use a proxy to intercept the original getter method, and load the actual data to the database or other third-party components when the object data is actually used, thus improving the system performance.

For example, the AOP in the great Spring framework is implemented using dynamic proxies.

Conclusion
The design pattern summarizes and refines previous work. Generally, the widely-spread design patterns are mature solutions for a specific problem. The rational use of design patterns not only makes the system more easily understood by others, but also gives the system a more reasonable structure. This article introduces four types of roles in the proxy mode, such as delayed loading and dynamic proxy, and hopes to help readers further understand the proxy mode.

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.