Proxy mode
1. In life:
An agent is the real life of a person or an organization that represents someone else to do something. In some cases, a client does not want or cannot refer directly to an object, whereas a proxy object can act as an intermediary between the client and the target object.
2. Official:
The proxy mode is the structure pattern of the object. Proxy mode provides a proxy object for an object, and the proxy object controls the reference to the original object
First, static agent
The class diagram structure is as follows
Roles in proxy mode:
Abstract topic Role: A common interface that declares 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 that the proxy object represents.
Agent topic Role: The proxy object contains a reference to the target object, so that the target object can be manipulated at any time, and the proxy object provides the same interface as the target object so that the target object can be substituted at any time. Proxy objects typically perform an operation before or after a client call is passed to the target object, rather than simply passing the call to the target object. It can add features that are not available in real-world themes.
Life Example: The New Year overtime more busy, no time to buy train tickets, then you can make a call to the nearby ticketing center, ask them to help you buy a home train ticket, of course, this will add additional labor costs. But to clear the ticket center itself does not sell tickets, only the railway station to really sell tickets, ticket center to sell you tickets in fact through the railway station to achieve. This is important!
Above This example, you are "customer", ticket Center is "Agent role", railway station is "real role", selling tickets called "Abstract role"!
Code
Abstract theme Roles
//抽象角色:声明真实对象和代理对象的共同接口;publicinterface TicketManager { /** * 售票 */ public void soldTicket(); /** * 改签 */ publicvoidchangeTicket(); /** * 退票 */ publicvoidreturnTicket();}
Real theme Characters
Public class Ticketmanagerimpl implements Ticketmanager { @Override Public void Soldticket() {//checkidentity ();System.out.println ("Ticketing"); }@Override Public void Changeticket(){//checkidentity ();System.out.println ("Change the sign"); }@Override Public void Returnticket() {//checkidentity ();System.out.println ("Refund"); }/** * Authentication * * * Public void checkidentity() {System.out.println ("Authentication"); }}
Agent topic Role (authentication feature added)
Public class Staticproxyticketmanager implements Ticketmanager {Ticketmanager Ticketmanager;//reference to the target object 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 agent-themed role (added log feature)
//proxy class implements the same interface Public class logproxy implements Ticketmanager {Ticketmanager Ticketmanager;//reference to the target class Public Logproxy(Ticketmanager Ticketmanager) { This. Ticketmanager=ticketmanager; }@Override Public void Soldticket() {ticketmanager.soldticket (); Log ();//rear-mounted enhancements}@Override Public void Changeticket() {ticketmanager.changeticket (); Log (); }@Override Public void Returnticket() {ticketmanager.returnticket (); Log (); }//Enhanced Private void Log() {System.out.println ("Log ..."); }}
Client
publicclass Test { publicstaticvoidmain(String[] args) { //装饰模式 new TicketManagerImpl() 真实的目标对象 //TicketManager tm=new StaticProxyTicketManager(new TicketManagerImpl()); TicketManager tm=new LogProxy(new StaticProxyTicketManager(new TicketManagerImpl())); tm.soldTicket(); tm.changeTicket(); tm.returnTicket(); }}
Results:
Authentication ———— –
Ticket
Log...
Authentication ———— –
Change sign
Log...
Authentication ———— –
Change sign
Log...
From the above example can be seen from the client through the agent to buy tickets and agents actually can not sell tickets to the customer, he is actually sold through the target object to the customer, that is, he is through the real theme of the target object to the client to sell the function of the ticket, he is only an intermediary, but we can add some features in it, such as authentication or advertising and other functions.
Static proxy class: Before the program runs, the. class file for the proxy classes already exists and the object being proxied is determined
Static Proxy:
Pros: Encapsulation of real objects does not modify the code of the target class.
Disadvantages:
1. When a proxy is required for several different types of target objects, I need to create multiple proxy classes that cause the expansion of the class
2. Redundancy of the Code
3. The compilation period is not flexible enough to join
Second, dynamic agent
Description (This description is seen from the Internet, relatively easy to understand)
Dynamic proxy: Dynamic proxies are more flexible than static proxies because they do not have to specify a proxy class to proxy a proxy object when we design the implementation, and we can defer this designation until the runtime is implemented by the JVM.
The so-called proxy, that is, the proxy class and the proxy class have the same external interface or service, so the proxy class generally must implement all the proxy class has been implemented interface, because the interface is to develop a series of external services standards.
1.JDK Implement Dynamic Proxy
Because dynamic proxies have such a flexible nature, we do not have to explicitly implement the same interface (interface) as the real topic class (Realsubject) When designing the Dynamic proxy class (Dynamicproxy), but defer this implementation to runtime.
In order for the Dynamicproxy class to be able to implement a series of interfaces implemented by the Realsubject class at runtime and to perform the associated method operations in the interface, it is necessary to The Dynamicproxy class implements the Java.lang.reflect.InvocationHandler interface that comes with the JDK, and the Invoke () method in the interface allows the Dynamicproxy instance to invoke the "external service" of the proxy class at run time. That is to call the method in all interfaces that the proxy class needs to implement externally, that is, to complete the invocation of the real method, which is called the real method in the Java Help document as the handler.
As stated above, we must first load all the interface that have been implemented by the proxy class realsubject into the JVM, otherwise how can the JVM find these methods? Understand this, then we can create an instance of the proxy class to get the class loader ClassLoader for that instance.
The so-called ClassLoader, ClassLoader, is a class definition with a class, that is, the internal related structure of the class (including the inheritance tree, the method area, and so on).
More importantly, the dynamic proxy pattern allows us to extend and enhance the original "real method" without altering the existing code structure, and can achieve the purpose of controlling the behavior of the Proxied object. Please take a look at the Dynamicproxy class in the code below, where the Invoke () method that must be implemented can perform certain special operations before and after invoking the real method of the proxy class. This is the most obvious advantage of dynamic agents
Class diagram
Code
ImportJava.lang.reflect.InvocationHandler;ImportJava.lang.reflect.Method;ImportJava.lang.reflect.Proxy; Public class Dynamicproxyticketmanager implements Invocationhandler { PrivateObject TargetObject;/** * Target initialization method, generate proxy class according to target * * @param targetObject * @return * / PublicObjectnewproxyinstance(Object TargetObject) { This. TargetObject = TargetObject;///first parameter, loader for target object ///second parameter, all interfaces implemented by the target interface, and these are the list of interfaces to be implemented by the dynamic proxy class The third parameter, called the implementation of the Invocationhandler object generation dynamic Proxy instance, when you call the proxy, the agent will call the Invocationhandler Invoke method returnProxy.newproxyinstance (Targetobject.getclass (). getClassLoader (), Targetobject.getclass (). GetInterfaces (), This); }/** * Reflection so that you can invoke a method of a class based on the configured parameters without knowing the specific class. Very useful in flexible programming. */ @Override PublicObjectInvoke(Object Proxy, Method method, object[] args)throwsThrowable {//CheckCheckidentity (); Object ret =NULL;Try{//Call target methodret = Method.invoke (targetObject, args);//Successful execution, print success informationLog (); }Catch(Exception e) {E.printstacktrace ();//failure, print failure informationSystem.out.println ("Error-->>"+ Method.getname ());ThrowE }returnRet }/** * Authentication * * * Public void checkidentity() {System.out.println ("Authentication--------------"); } Public void Log() {System.out.println ("Log ..."); }}
Client
publicclass Test { publicstaticvoidmain(String[] args) { DynamicProxyTicketManager dynamicProxyTicketManager=new DynamicProxyTicketManager(); TicketManager tm=(TicketManager) dynamicProxyTicketManager.newProxyInstance(new TicketManagerImpl()); tm.soldTicket(); tm.changeTicket(); tm.returnTicket(); }}
Results Ibid.
Advantages and Disadvantages
Advantages:
1, a dynamic proxy class is more simple, can solve the problem of creating multiple static agents, to avoid repeated redundant code
2, call the target code, will be in the method "runtime" dynamic join, determine what type you are, only adjust who, flexible
Disadvantages:
1, the system is flexible, but compared to the efficiency is reduced, a little slower than the static agent
2, dynamic agent than static proxy in the readability of the code a little bit, not easy to understand
3, JDK dynamic Agent can only implement the interface of the class to proxy
Summarize
Each has the good, the concrete situation concrete discussion
2.Cglib Implement Dynamic Proxy
Description (Online collation)
The source code for AOP uses two dynamic proxies to enable interception: the JDK dynamic agent and the Cglib dynamic agent.
Two methods exist at the same time, each has advantages and disadvantages. The JDK dynamic agent is implemented by the reflection mechanism inside Java, and the Cglib dynamic agent is implemented by ASM. In general, the reflection mechanism is more efficient in generating classes, and ASM is more efficient in the execution of the class after it is generated (you can cache the ASM-generated classes to solve the ASM-generated class-process inefficiencies). It is also important to note that the application premise of the JDK dynamic agent must be the target class based on the unified interface. The JDK dynamic agent cannot be applied without the above premise. It can be seen that the JDK dynamic agent has certain limitations, cglib this third-party class library Implementation of the dynamic proxy application more extensive, and more efficient advantages.
The dynamic agent mechanism of the JDK can only proxy the class that implements the interface, otherwise it can't implement the dynamic proxy of the JDK, Cglib is to implement the proxy for the class, his principle is to generate a subclass for the specified target class and overwrite the method implementation enhancement, but because inherit is used, Therefore, the final decorated class cannot be proxied.
Introduced:
Core classes of Cglib:
net.sf.cglib.proxy.enhancer– Major Enhancement classes
net.sf.cglib.proxy.methodinterceptor– the Main method interception class, which is a sub-interface of the callback interface, requires the user to implement
The proxy class of the Java.lang.reflect.Method class of NET.SF.CGLIB.PROXY.METHODPROXY–JDK can easily implement the invocation of the source object method, such as using:
Object o = Methodproxy.invokesuper (proxy, args);//Although the first parameter is a proxy object, there is no problem with the dead loop.
The Net.sf.cglib.proxy.MethodInterceptor interface is the most common type of callback (callback), and it is often used by proxy-based AOP to implement a call to intercept (intercept) methods. This interface only defines a method
public object Intercept (Object object, Java.lang.reflect.Method Method,
Object[] args, Methodproxy proxy) throws Throwable;
The first parameter is the proxy pair image, 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, as it is faster
Code
Public class Cglibdynamicproxyticketmanager implements methodinterceptor { PrivateObject TargetObject;//target object /** * Create proxy Object * * @param targetObject * @return * * PublicObjectgetinstance(Object TargetObject) { This. TargetObject = TargetObject; Enhancer enhancer =NewEnhancer ();//Use this class to create a proxy object (subclass of the proxy Class): and set the parent class; set the callback;Enhancer.setsuperclass ( This. Targetobject.getclass ());//Set the proxy class as the proxy target for its parent class //callback methodEnhancer.setcallback ( This);//Set Callback--callback method Intercept () is executed when the method of this proxy object is invoked //Create proxy object returnEnhancer.create (); }@Override //callback method //Methodproxy method of the proxy class /** * Methodproxy will invoke the proxy method of the parent class (the target object), such as the Soldticket method, etc. */ PublicObjectIntercept(Object obj, method method, object[] args, Methodproxy methodproxy)throwsthrowable {Object result =NULL; Checkidentity ();//front-mounted enhancementsResult=methodproxy.invokesuper (obj, args);//Call the Proxy method of the parent class to which the newly generated Cglib proxy object belongsLog ();//rear-mounted enhancements returnResult }/** * Authentication * * * Public void checkidentity() {System.out.println ("Authentication--------------"); } Public void Log() {System.out.println ("Log ..."); }}
Client
publicclass Test { publicstaticvoidmain(String[] args) { CglibDynamicProxyTicketManager cglibdynamicProxyTicketManager=new CglibDynamicProxyTicketManager(); //生成代理对象 TicketManager tm=(TicketManager) cglibdynamicProxyTicketManager.getInstance(new TicketManagerImpl()); tm.soldTicket();//当调用代理对象的被代理对象的方法时 会自动回调 代理类中的Intercept()方法 tm.changeTicket(); tm.returnTicket(); }}
Results Ibid.
Java design mode (eight)----proxy mode