Java design mode (8)-proxy Mode

Source: Internet
Author: User

Java design mode (8)-proxy Mode

Proxy Mode
1. in life:
Proxy is a real life in which one person or organization represents others to do one thing. In some cases, a client does not want or cannot directly reference an object, and the proxy object can play a mediation role between the client and the target object.
2. Official:
The proxy mode is the structure mode of the object. The proxy mode provides a proxy object for an object and controls the reference to the original object by the proxy object.

I. Static proxy

The class chart structure is as follows:


Role in proxy mode:
● Abstract topic role: Declares the common interfaces of the target object and the proxy object, so that the proxy object can be used wherever the target object can be used.
● Real topic role: defines the target object represented by the proxy object.
● Proxy topic role: the proxy object contains references of the target object, so that the target object can be operated at any time. The proxy object provides the same interface as the target object, so that the target object can be replaced at any time. A proxy Object usually performs an operation before or after the client call is passed to the target object, instead of simply passing the call to the target object. It can add features not available in real themes.

Example in my life: I am busy working overtime for the Chinese New Year. I don't have time to buy a train ticket. Now I can call a ticket center to ask them to buy a train ticket for me to go home, of course, additional labor fees will be attached. However, it should be clear that the ticket center does not sell tickets. Only the railway station actually sells tickets. The ticket center actually sells tickets to you through the railway station. This is important!
In the above example, you are a "customer", the ticket center is "agent role", the railway station is "real role", and the ticket sales is called "abstract role "!

Code
Abstract topic role

// Abstract role: declare the common interfaces of real objects and proxy objects; public interface TicketManager {/*** Ticket */public void soldTicket (); /*** change sign */public void changeTicket ();/*** refund */public void returnTicket ();}

Real topic role

Public class TicketManagerImpl implements TicketManager {@ Override public void soldTicket () {// checkIdentity (); System. out. println ("ticket") ;}@ Override public void changeTicket () {// checkIdentity (); System. out. println ("change") ;}@ Override public void returnTicket () {// checkIdentity (); System. out. println ("refund");}/*** authentication */public void checkIdentity () {System. out. println ("authentication ");}}

Proxy topic role (added the authentication function)

Public class StaticProxyTicketManager implements TicketManager {TicketManager ticketManager; // reference public StaticProxyTicketManager (TicketManager ticketManager) {this. ticketManager = ticketManager;} @ Override public void soldTicket () {checkIdentity (); ticketManager. soldTicket () ;}@ Override public void changeTicket () {checkIdentity (); ticketManager. changeTicket () ;}@ Override public void returnTicket () {checkIdentity (); ticketManager. changeTicket ();}/*** authentication */public void checkIdentity () {System. out. println ("authentication --------------");}}

Second proxy topic role (Added log function)

// The proxy class implements the same interface public class LogProxy implements TicketManager {TicketManager ticketManager; // reference public LogProxy (TicketManager ticketManager) {this. ticketManager = ticketManager;} @ Override public void soldTicket () {ticketManager. soldTicket (); log (); // post enhancement} @ Override public void changeTicket () {ticketManager. changeTicket (); log () ;}@ Override public void returnTicket () {ticketManager. returnTicket (); log () ;}// enhance private void log () {System. out. println ("log... ");}}

Client

Public class Test {public static void main (String [] args) {// decoration Mode new TicketManagerImpl () real target object // TicketManager tm = new StaticProxyTicketManager (new TicketManagerImpl (); TicketManager tm = new LogProxy (new StaticProxyTicketManager (new TicketManagerImpl (); tm. soldTicket (); tm. changeTicket (); tm. returnTicket ();}}

Result:
Identity Authentication -----
Ticket sales
Logs...
Identity Authentication -----
Change Signature
Logs...
Identity Authentication -----
Change Signature
Logs...
From the example above, we can see that the client purchases tickets through proxy, but the agent cannot sell tickets to the customer. In fact, the client actually sells tickets to the customer through the target object, that is to say, he is using the target object of the real theme to sell tickets to the client. He is only an intermediary, but we can add some functions in it, for example, identity verification, advertising, and other functions.

Static proxy class: before the program runs, the. class file of the proxy class already exists and the proxy object has been determined.
Static Proxy:
Advantage: encapsulates real objects without modifying the code of the target class.
Disadvantages:
1. When multiple target objects of different types need proxy, I need to create multiple proxy classes, resulting in class expansion.
2. Code Redundancy
3. added during compilation, not flexible enough

Ii. Dynamic proxy

Description (this description is relatively easy to understand from the Internet)
Dynamic Proxy: Compared with static Proxy, Dynamic Proxy is more flexible, because it does not need to specify a Proxy class to Proxy which is a Proxy object during our design and implementation, we can implement this specified delay by JVM when the program is running.
The so-called proxy requires that the proxy class has the same external interface or service as the proxy class. Therefore, the proxy class generally must implement all the interfaces already implemented by the proxy class, because interfaces are a series of external service standards.
1. JDK implements dynamic proxy

Because dynamic proxies have such flexible features, we do not need to explicitly implement interfaces that are the same as RealSubject when designing dynamic proxies ), however, this implementation is postponed to the runtime.
To enable the DynamicProxy class to implement a series of interfaces implemented by the RealSubject class and perform related method operations in the interface at runtime, The DynamicProxy class must implement the java built-in JDK. lang. reflect. invocationHandler interface. The invoke () method in this interface enables the DynamicProxy instance to call the "External Service" of the proxy class at runtime, that is, to call the methods in all interfaces that the proxy class needs to implement externally, that is, to call the real method, the Java help document calls these real methods as the processing program.
As described above, we must first load all interfaces implemented by the proxy class RealSubject into JVM. Otherwise, how can we find these methods? With this understanding, we can create an instance of the proxy class and obtain the ClassLoader of the instance.
The so-called ClassLoader refers to the class definition of a class, that is, the internal structure of the class (including the inheritance tree and method area ).
More importantly, the dynamic proxy mode enables us to expand and enhance the original "real method" without changing the existing code structure, in addition, it can control the behavior of the proxy. For details, see the DynamicProxy class in the following code. The required invoke () method can perform some special operations before and after calling the real method of the proxy class. This is the most obvious advantage of dynamic proxy

Class Diagram

Code

Import java. lang. reflect. invocationHandler; import java. lang. reflect. method; import java. lang. reflect. proxy; public class DynamicProxyTicketManager implements InvocationHandler {private Object targetObject;/*** the initialization method of the target, generate proxy class ** @ param targetObject * @ return */public Object newProxyInstance (Object targetObject) {this.tar getObject = targetObject; // The first parameter, the loader of the target object // The second parameter, all interfaces implemented by the target interface, which are dynamic The list of interfaces to be implemented by the Status proxy class // The third parameter. The InvocationHandler object is called to generate a dynamic proxy instance. When you call the proxy, the Proxy will call the InvocationHandler's invoke method return Proxy. newProxyInstance (targetObject. getClass (). getClassLoader (), targetObject. getClass (). getInterfaces (), this);}/*** reflection, so that you can call a class method based on the configured parameters without knowing the specific class. It is useful in flexible programming. * // @ Override public Object invoke (Object proxy, Method method, Object [] args) throws Throwable {// check checkIdentity (); Object ret = null; try {// call the target method ret = method. invoke (targetObject, args); // execution successful, print successful information log ();} catch (Exception e) {e. printStackTrace (); // when the error occurs, print the failure information System. out. println ("error -->" + method. getName (); throw e;} return ret;}/*** authentication */public void checkIdentity () {System. out. println ("authentication --------------");} public void log () {System. out. println ("log... ");}}

Client

public class Test {    public static void main(String[] args) {        DynamicProxyTicketManager dynamicProxyTicketManager=new DynamicProxyTicketManager();        TicketManager tm=(TicketManager) dynamicProxyTicketManager.newProxyInstance(new TicketManagerImpl());        tm.soldTicket();        tm.changeTicket();        tm.returnTicket();    }}

The result is the same as above.
Advantages and disadvantages
Advantages:
1. A dynamic proxy class is simpler. It can solve the trouble of creating multiple static proxies and avoid repeated redundant code.
2. When calling the target code, it will dynamically Add the method "RunTime" to decide what type you are, who to call, and flexible
Disadvantages:
1. The system is flexible, but the efficiency is lower than that of static proxy.
2. Dynamic proxy is a little less readable than static proxy and is not easy to understand.
3. JDK dynamic proxy can only proxy classes that implement interfaces
Summary
Each has its own merits and details

2. Implement Dynamic proxy using Cglib

Description (online sorting)
Two Dynamic proxies are used in the source code of AOP to implement the intercept and intercept functions: jdk dynamic proxy and cglib dynamic proxy.
Both methods exist at the same time, and each method has its own advantages and disadvantages. Jdk dynamic proxy is implemented by the java internal reflection mechanism, while cglib dynamic proxy is implemented by asm at the underlying layer. In general, the reflection mechanism is more efficient in the process of generating classes, while asm is more efficient in the execution process after the classes are generated (you can cache the classes generated by asm, this solves the problem of inefficiency in the Process of asm generation class ). Note: The premise of jdk dynamic proxy must be that the target class is based on a unified interface. Without the preceding prerequisites, jdk dynamic proxy cannot be applied. It can be seen that jdk dynamic proxy has some limitations. cglib, a third-party class library, implements a wider range of dynamic proxy applications and has more efficiency advantages.
JDK's dynamic proxy mechanism can only implement interface classes. Otherwise, JDK's dynamic proxy cannot be implemented. cglib implements proxy for classes, the principle is to generate a subclass for the specified target class and override the method to implement enhancement. However, because the class is inherited, the final modification class cannot be proxy.

Introduction:
CGLIB core class:
Net. sf. cglib. proxy. Enhancer-Main enhancement class
Net. sf. cglib. proxy. MethodInterceptor-main method interception class, which is a subinterface of the Callback interface and needs to be implemented by the user
Net. sf. cglib. proxy. MethodProxy-JDK's java. lang. reflect. Method class proxy class, you can conveniently call the source object Method, such as using:
Object o = methodProxy. invokeSuper (proxy, args); // although the first parameter is a proxy Object, there will be no endless loops.
The net. sf. cglib. proxy. MethodInterceptor interface is the most common callback type. It is often used by proxy-based AOP to call intercept methods. This interface only defines one method.
Public Object intercept (Object object, java. lang. reflect. Method method,
Object [] args, MethodProxy) throws Throwable;
The first parameter is the proxy object, and the second and third parameters are the parameters of the intercepted method and method, respectively. The original Method may be called by using the general reflection of the java. lang. reflect. Method object, or by using the net. sf. cglib. proxy. MethodProxy object. Net. sf. cglib. proxy. MethodProxy is usually preferred because it is faster

Code

Public class CglibDynamicProxyTicketManager implements MethodInterceptor {private Object targetObject; // target Object/*** create proxy Object *** @ param targetObject * @ return */public Object getInstance (Object targetObject) {this.tar getObject = targetObject; Enhancer enhancer = new Enhancer (); // use this class to create a proxy object (subclass of the proxy class): Set the parent class; set the callback; enhancer.setSuperclass(this.tar getObject. getClass (); // sets the proxy target to which the proxy class acts as its parent class. // The callback method enhancer. setCallback (this); // set the callback -- when the proxy object method is called, The callback method intercept () will be executed // create the proxy object return enhancer. create () ;}@ Override // callback method // method of the methodProxy proxy class/*** methodProxy calls the proxy method of the parent class (target object, for example, soldTicket Method */public Object intercept (Object obj, method Method, Object [] args, MethodProxy methodProxy) throws Throwable {Object result = null; checkIdentity (); // pre-enhancement result = methodProxy. invokeSuper (obj, args); // call the log () method of proxy for the parent class of the newly generated cglib proxy object; // post-enhancement return result ;} /*** authentication */public void checkIdentity () {System. out. println ("authentication --------------");} public void log () {System. out. println ("log... ");}}

Client

Public class Test {public static void main (String [] args) {CglibDynamicProxyTicketManager cglibdynamicProxyTicketManager = new ticket (); // generate a proxy object TicketManager tm = (TicketManager) ticket. getInstance (new TicketManagerImpl (); tm. soldTicket (); // when the method of the proxy object to be called is called, the Intercept () method tm in the proxy class is automatically called. changeTicket (); tm. returnTicket ();}}

The result is the same as above.

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.