Java Dynamic Agents (JDK and Cglib)

Source: Internet
Author: User
Tags throwable

Dynamic Agent for Java
Proxy mode
Proxy mode is a common Java design pattern, his characteristic is that the proxy class and the delegate class have the same interface, the proxy class is mainly responsible for the delegate class preprocessing messages, filtering messages, forwarding messages to the delegate class, and post-processing messages. There is usually an association between the proxy class and the delegate class, and the object of a proxy class is associated with an object of a delegate class, and the object of the proxy class does not actually implement the service, but instead provides a specific service by invoking the related method of the object of the delegate class.
The proxy class can be divided into two types according to the agent's creation period.
Static proxy: The source code is generated automatically by the programmer or a specific tool, and then compiled. Before the program runs, the. class file for the proxy classes already exists.
Dynamic Agent: When the program is running, it is created dynamically using the reflection mechanism.

First look at the static proxy:

1.cat.java

 Package proxy; /**  */Publicinterface  car    {//  View car method     publicvoid  querycar ();     // Modifying car methods     Public void Updatecar ();}

2.carimpl.java

 Package proxy; /**  */Publicclassimplements  Car    {    @Override  publicvoid  Querycar () {        System.out.println ("View Car method ...");    @Override    publicvoid  Updatecar () {        System.out.println ("View Car method ...");    }}

3.carproxy.java

 Packageproxy; Public classCarproxyImplementsCar {PrivateCarimpl Carimpl; /*** Override default constructor * *@paramCarimpl*/     Publiccarproxy (Carimpl carimpl) { This. Carimpl =Carimpl; } @Override Public voidQuerycar () {System.out.println ("Before transaction processing"); //the method of invoking the delegate class;Carimpl.querycar (); System.out.println ("After transaction processing"); } @Override Public voidUpdatecar () {System.out.println ("Before transaction processing"); //the method of invoking the delegate class;Carimpl.updatecar (); System.out.println ("After transaction processing"); }}

4.TestCar (Test call Class)

 Package proxy;  Public class Testcar {    publicstaticvoid  main (string[] args) {          New  Carimpl ();         New Carproxy (Countimpl);        Carproxy.updatecar ();        Carproxy.querycar ();    }}

Observation code can find that each proxy class can only serve one interface, so that the development of the program will inevitably generate too many agents, and all the agent operation in addition to the method called, the other operations are the same, then it must be duplicated code. The best way to solve this problem is to complete the proxy function through a proxy class, which must be done using dynamic proxy.


Let's take a look at the dynamic proxy:
The JDK dynamic agent contains a class and an interface:
Invocationhandler Interface:
Public interface Invocationhandler {
public object Invoke (Object Proxy,method method,object[] args) throws Throwable;
}


Parameter description:
Object proxy: Refers to the objects being proxied.
Method: Methods to invoke
object[] args: Parameters required for method invocation

The subclass of the Invocationhandler interface can be imagined as a proxy's final operation class, replacing the Proxysubject.

Proxy class:
The proxy class is an action class that specifically completes the proxy, which can be used to dynamically generate an implementation class for one or more interfaces, which provides the following operations:
public static Object newproxyinstance (ClassLoader loader, class<?>[] interfaces,
Invocationhandler h) throws IllegalArgumentException

Parameter description:
ClassLoader Loader: Class loader
Class<?>[] Interfaces: Get all the interfaces
Invocationhandler h: Get subclass instance of Invocationhandler interface

Ps: Class Loader
In the proxy class in the Newproxyinstance () method requires an instance of the ClassLoader class, ClassLoader actually corresponds to the class loader, in Java, there are three kinds of loaders;
Booststrap ClassLoader: This loader is written in C + + and is not visible in general development;
Extendsion ClassLoader: Used to load the extension class, generally corresponding to the class in the Jre\lib\ext directory;
Appclassloader: (default) Loads the class specified by Classpath, which is most commonly used as an loader.

Dynamic Agent
Compared with the static proxy class, dynamic proxy class, the bytecode of dynamic proxy class is generated dynamically by the Java reflection mechanism when the program runs, without the programmer writing its source code manually. The dynamic proxy class not only simplifies programming, but also improves the scalability of the software system, because the Java reflection mechanism can generate any type of dynamic proxy class. The proxy class and the Invocationhandler interface in the Java.lang.reflect package provide the ability to generate dynamic proxy classes.

Dynamic Proxy Example:

1.Animal

 Package Axny; /**  */Publicinterface  Animal    {publicvoid  Addanimal ();}

2.AnimalImpl

 Package Axny; /**  */Publicclassimplements  Animal    {    @Override  publicvoid  addanimal () {        System.out.println ("Increase animal methods ... ");    }}

3.AnimalProxy

 PackageAxny;ImportJava.lang.reflect.InvocationHandler;ImportJava.lang.reflect.Method;ImportJava.lang.reflect.Proxy;/*** proxy class*/ Public classAnimalproxyImplementsInvocationhandler {PrivateObject Target; /*** Bind the delegate object and return a proxy class *@paramTarget *@return     */     Publicobject bind (object target) { This. target =Target; //Get proxy Object        returnproxy.newproxyinstance (Target.getclass (). getClassLoader (), Target.getclass (). Getinterfaces (), This); } @Override PublicObject Invoke (Object proxy, Method method, object[] args)throwsthrowable {Object result=NULL; System.out.println ("Transaction Start"); //Execution Methodresult =Method.invoke (target, args); System.out.println ("End of Transaction"); returnresult; }}

4.AnimalTest

 Package Axny;  Public class animaltest {    publicstaticvoid  main (string[] args) {        new  animalproxy ();         = (Animal) proxy.bind (new  Animalimpl ());        Animalproxy.addanimal ();    }}

Output:

Things start
Increase the animal method ...
The end of Things

However, the dynamic proxy of the JDK relies on the interface, and if some classes do not implement the interface, then the JDK proxy cannot be used, which will use the Cglib dynamic proxy.

Cglib Dynamic Agent
The dynamic agent mechanism of JDK can only implement the class of the interface, and the class that cannot implement the interface cannot implement the dynamic proxy of the JDK, the cglib is to implement the proxy for the class, his principle is to generate a subclass for the target class, and overwrite the method implementation enhancement, but because inherit is adopted, Therefore, the final decorated class cannot be proxied.
Example:

1.animalproxycglib.java

 PackageCG;ImportJava.lang.reflect.Method;ImportNet.sf.cglib.proxy.Enhancer;ImportNet.sf.cglib.proxy.MethodInterceptor;ImportNet.sf.cglib.proxy.MethodProxy;/*** Use cglib dynamic agent * *@authorStudent **/ Public classAnimalproxycglibImplementsMethodinterceptor {PrivateObject Target; /*** Create proxy Object * *@paramTarget *@return     */     Publicobject GetInstance (object target) { This. target =Target; Enhancer Enhancer=Newenhancer (); Enhancer.setsuperclass ( This. Target.getclass ()); //callback MethodEnhancer.setcallback ( This); //Create a proxy object        returnenhancer.create (); } @Override//callback Method     PublicObject Intercept (Object obj, Method method, object[] args, methodproxy proxy)throwsthrowable {System.out.println ("Things start.");        Proxy.invokesuper (obj, args); System.out.println ("The end of things."); return NULL; }}

2.testcglib.java

 Package CG; Import Axny. Animalimpl;  Public class Testcglib {    publicstaticvoid  main (string[] args) {        Animalproxycglib cglib=new  animalproxycglib ();        Animalimpl bookcglib= (Animalimpl) cglib.getinstance (new  Animalimpl ());        Bookcglib.addanimal ();    }}

The output is the same:

Things start
Increase the animal method ...
The end of Things

Difference:

First, from the number of files, Cglib is less than the JDK implementation of an interface class. Because the proxy object returned by Cglib is a subclass of the target object. Both the proxy object and the target object generated by the JDK implement a common interface.

Dynamic Agent:

dynamic agents are divided into two         types: *  JDK Dynamic proxy          *   proxy object and target object implement common interface          *   Interceptor must implement Invocationhanlder interface           *  cglib Dynamic proxy          *   Proxy         object is a subclass of the target object *   Interceptors must implement Methodinterceptor interface          *  Session.load in Hibernate is implemented by Cglib

Java Dynamic Agents (JDK and Cglib)

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.