Java Dynamic Agent

Source: Internet
Author: User
Tags aop throwable

Proxy mode refers to providing a proxy object to an object that the user does not directly access to the original object but indirectly through the proxy object.

We can use the proxy pattern to implement aspect-oriented programming (AOP), which is used by dynamic agents to weave the slice functionality into the target method without intruding into the caller's business code.

or using proxy mode to implement remote procedure call (RPC), the caller invokes the proxy method as if it were a local method without having to worry about the proxy calling the remote method details.

The JDK provides a dynamic proxy implementation based on the reflection mechanism, while the widely used third-party library, Cglib, implements dynamic proxies based on the bytecode manipulation framework asm.

In this paper, we will briefly introduce two dynamic proxy usage methods.

Content

    • Proxy mode
    • Java Dynamic Agent
    • Cglib Dynamic Agent
Proxy mode

Implementing the static proxy pattern is very simple, first we define an interface:

publicinterface MyInterface {    voidfoo();}

Write the object that is being proxied:

publicclassimplements MyInterface {    @Override    publicvoidfoo() {        System.out.println("foo");    }}

Classes that are proxied in proxy mode are often referred to as delegate classes.

To write a static proxy:

public   myproxy implements  myinterface {private  MyInterface    Subject myproxy  (MyInterface subject) {this .    subject  = subject; }  @Override  public  void   () {long  start = System.. currenttimemillis         (); Subject. foo         (); long  elapsetime = System. currenttimemillis         ()-Start; System. out . println     ( "elapse time:"  + elapsetime); }}

A static proxy is a proxy class that is generated at compile time, and the relative dynamic proxy is the bytecode of the runtime generation proxy class and loaded into the JVM.

The problem with static proxies is that you must understand the details of the interface when you write the proxy class- MyProxy the definition that you must understand when writing MyInterface .

In the case of an AOP framework, the framework does not know beforehand that interface information can only create proxy objects from class objects at run time, so writing such a framework must be supported by dynamic proxy mechanisms.

Java Dynamic Agent

The reflection mechanism of Java can create classes at run time, and the Java Standard Library provides a reflection-based proxy mechanism.

The proxy class should implement java.lang.reflect.InvocationHandler an interface that has only one method: invoke .

publicinvoke(Object proxy, Method method, Object[] args)    throws Throwable;

The Invoke method of the proxy class is invoked when we access the delegate class method through the proxy. We can get the invocation information through the parameters of the Invoke method, and call the method of the delegate class using the reflection mechanism.

The three parameters of the Invoke method are:

    • Object porxy: The dynamic proxy instance of the invoked method
    • Method method: The method being called
    • Object[] args: Parameters passed in when called

java.lang.reflect.Proxy.newProxyInstancemethod is used to create a proxy object that uses the reflection mechanism to create a proxy class and load it into the JVM at run time. The method has three parameters:

    • ClassLoader loader: Loading the Agent class loader
    • Class<?>[] interfaces: The method to be implemented by the proxy class
    • InvocationHandler h: When invoking the proxy class method, embed the Invocationhandler instance of the calling procedure

The direct description is more difficult to understand, let's look at the code:

 Public classMyproxyImplementsInvocationhandler {PrivateObject subject; Public myproxy(Object subject) { This.subject= subject; }@Override     PublicObjectInvoke(Object Proxy, Method method, object[] args)throwsThrowable {//1        returnMethod.Invoke(subject, args); }@SuppressWarnings("Unchecked") Public Static<T> TCreateproxy(T subject) {returnT Proxy.newproxyinstance(subject.GetClass().getClassLoader(),//2Subject.GetClass().getinterfaces(),New myproxy(subject)); } Public Static void Main(string[] args) {MyInterface obj =Createproxy(New MyService());//3Obj.Foo(); }}

MyInterfaceand MyService exactly the same as above:

publicinterface MyInterface {    voidfoo();}publicclassimplements MyInterface {    @Override    publicvoidfoo() {        System.out.println("foo");    }}

MyProxyThe class implements the InvocationHandler interface and provides a createProxy static method.

In the main method we MyService created a proxy for the object and called the method through the proxy foo .

There are several details in the code that are worth knowing:

  1. In the method, the main obj.getClass().getName() class name by obtaining the proxy class is: com.sun.proxy.$Proxy0 . This class name indicates that the class is a dynamically generated proxy class, and 0 indicates that it is the first dynamic proxy class in the current JVM.

  2. At note 2 We newProxyInstance created the proxy class, which is the class in the preceding section $Proxy0 :
    1. loaderis the loader for the class being proxied and can also be used MyInterface.class.getClassLoader() , both of which are appclassloader instances.
    2. interfacesParameters are subject.getClass().getInterfaces() all interfaces that represent the dynamic proxy class that $Proxy0 implement subject, but are $Proxy0 not subclasses of the subject class.
      It is therefore main used in methods MyInterface obj = createProxy(new MyService()); and cannot be used MyService obj = createProxy(new MyService()); .
    3. We use the MyProxy instance as Invocationhandler to intercept all method calls of the dynamic proxy class.
  3. At note 1 We implemented a invoke method to intercept all method invocations of the dynamic proxy object:
    1. The passed-in argument is an instance of the Object proxy dynamic proxy class, which main is the method, which is an instance of the obj $Proxy0 class. Note The Invocationhandler instance is not a dynamic proxy instance, and handler is a static class generated by the compilation.
    2. The passed-in argument Method method is the method object of the interface class, MyInterface.class.getMethod("foo") not MyService the method object of the delegate class
    3. method.invoke(subject, args)The method of the proxy instance is invoked in a reflective manner, and we can invoke add additional code to the method to enhance the function of the delegate class
Cglib Dynamic Agent

Cglib is a powerful dynamic agent library, SPRINGAOP and DYNAOP frameworks use Cglib for method interception and enhancement, Hibernate uses Cglib for proxy affinity, and Jmock also uses Cglib to provide mock objects.

On the implementation, Cglib uses the high-performance lightweight bytecode manipulation framework ASM to dynamically generate proxy classes. It is worth mentioning that Cglib is faster than the JDK dynamic agent.

Cglib implements a dynamic proxy class as a subclass of a delegate class, so you can delegate classes that do not implement an interface or extend an interface. Because subclasses cannot overwrite the final method, they can only proxy non-final methods.

First use MAVEN to import cglib dependencies:

<dependency>    <groupId>cglib</groupId>    <artifactId>cglib</artifactId>    <version>3.2.6</version></dependency>

To write a cglib dynamic agent:

 Public classCglibproxy {@SuppressWarnings("Unchecked") Public Static<T> TCreateproxy(T subject) {Enhancer Enhancer =New Enhancer(); Enhancer.Setsuperclass(subject.GetClass()); Enhancer.Setcallback(New Myinterceptor());return(T) enhancer.Create(); }Private Static classMyinterceptorImplementsMethodinterceptor {@Override         PublicObjectIntercept(Object obj, method method, object[] args, Methodproxy proxy)throwsThrowable {returnProxy.Invokesuper(obj, args); }    } Public Static void Main(string[] args) {MyService obj =Createproxy(New MyService()); Obj.Foo(); }}

EnhancerUsed to enhance the delegate class, which can intercept method calls to implement the proxy mechanism.

MethodInterceptor.interceptmethod is used to intercept a method call, and several of its parameters are:

    • Object obj: Dynamic Proxy Object
    • Method method: The method that is intercepted, the method that is intercepted in this example main is:MyService.class.getMethod("foo")
    • Object[] args: Invoke argument
    • MethodProxy proxy: The shortcut proxy used to invoke the delegate class method, not the dynamic proxy class.

The dynamic agent defined in the example does not add any additional functionality, and this special callback can be used net.sf.cglib.proxy.NoOp instead:

    publicstaticcreateProxy(T subject) {        newEnhancer();        enhancer.setSuperclass(subject.getClass());        enhancer.setCallback(NoOp.INSTANCE);        return (T) enhancer.create();    }

Enhancer can use Callbackfilter to configure filters for each method call:

classMyService {void Foo0() {System. out.println("0"); }void foo1() {System. out.println("1"); }} Public classCglibproxy {@SuppressWarnings("Unchecked") Public Static<T> TCreateproxy(T subject) {Enhancer Enhancer =New Enhancer(); Enhancer.Setsuperclass(subject.GetClass()); Callback callback0 = NoOp.INSTANCE; Callback callback1 = NoOp.INSTANCE; Enhancer.Setcallbacks(NewCallback[]{callback0, callback1}); Enhancer.Setcallbackfilter(New Mycallbackfilter());return(T) enhancer.Create(); }Private Static classMycallbackfilterImplementsCallbackfilter {@Override         Public int Accept(method) {if("Foo0".equals(method.GetName())) {return 0; }Else{return 1; }        }    } Public Static void Main(string[] args) {MyService obj =Createproxy(New MyService()); Obj.Foo0(); Obj.foo1(); }}

After enhancer sets the Callbackfilter, the method is called before the method is intercepted to CallbackFilter.accept() determine which callback instance to use for interception.

CallbackFilter.accept()The return value is the subscript of the interceptor, and the even if accept method returns 0, and the call is enhancer.callbacks[0] intercepted.

Java Dynamic Agent

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.