Dynamic proxy for jdk and CGLIB

First look at the dynamic proxy implemented by jdk:

It can only generate proxies for classes that implement interfaces, not for classes. In other words, if the target object implements the interface, it will use jdk's dynamic proxy by default.

Now let's use the simplest code example to see how to implement the process of dynamic proxy:

package flex.cc.financialManagement.accountReceivable.web;

public interface TestService {
	public void say();//Define a test method
}

His implementation class is also the class to be proxied:

package flex.cc.financialManagement.accountReceivable.web;

public class TestServiceImpl implements TestService{

	@Override
	public void say() {
		System.out.println("I am the target object of jdk dynamic proxy!");
	}

}

This is what we usually use before, there is nothing new. Next, we will use jdk's dynamic proxy to enhance the TestServiceImpl class. First of all, we need to know that if we want to implement jdk's dynamic proxy, we must implement the InvocationHandler interface. , this is required, and then override his invoke method.

package flex.cc.financialManagement.accountReceivable.web;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class TestJDKImpl implements InvocationHandler{

	private Object obj;
	//create proxy object
	public Object bind(Object obj){
		this.obj=obj;
		return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this);
	}
	@Override
	public Object invoke(Object proxy, Method method, Object[] arg2)
			throws Throwable {
		// TODO Auto-generated method stub
		System.out.println("------The operation before the method!------");
		Object invoke = method.invoke(obj, arg2);//Pay special attention here
		System.out.println("The operation after the ++++++ method! ++++++");
		return invoke;
	}
}
The bind method here is the method of generating the proxy object. This process is basically the logic of writing to death, and there are no skills. It explains the meaning of the parameters in newProxyInstance: the first parameter means the loader of the target object; the second parameter is: the interface type of the target object; the third parameter is: this parameter is very important after the proxy object is generated On which object when we call the method, mark the object of TestJDKImpl here.

Explain the generated proxy object passed by the first parameter of invoke, and the obj passed in method.invoke(obj, arg2); is the proxy object, don't confuse it.

Finally, let's test:

package flex.cc.financialManagement.accountReceivable.web;

public abstract class Test1 {

	public static void main(String[] args) {
		TestService b=new TestServiceImpl();
		TestJDKImpl a=new TestJDKImpl();
		TestService bind = (TestService) a.bind(b);//Proxy object
		bind.say();
	}
}

The output is as follows:

------ The operation before the method! ------
I am the target object of jdk dynamic proxy!
++++++ operation after method! ++++++

It is enhanced before and after the original method; this process is a simple implementation of jdk dynamic proxy. It should also be emphasized here why calling the say() method of the proxy object in the test will execute the invoke method in TestJDKImpl. I didn't understand why at first, but a great god gave an explanation:

http://rejoy.iteye.com/blog/1627405
If you are interested, you can check it out for yourself;


Next, let's implement the CGLIB dynamic proxy:

The difference from JDk dynamic proxy is that CGLIB dynamic proxy is a proxy for class implementation; in other words, a dynamic proxy of a class that does not implement an interface must use CGLIB to implement dynamic proxy; create a target class:

package flex.cc.financialManagement.accountReceivable.web;

public class TestCglibimpl {

	public void say(){
		System.out.println("I am CGLIB dynamic proxy!");
	}
}

To implement CGLIB dynamic proxy, you need to implement the MethodInterceptor interface and dynamically generate the proxy subclass, so you can't implement proxy for the final modified class.

package flex.cc.financialManagement.accountReceivable.web;

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 CreatCglibModel implements MethodInterceptor{

	private Object o;
	public Object getObject(Object obj){
		o=obj;
		Enhancer enhancer=new Enhancer();
		enhancer.setSuperclass(obj.getClass());
		enhancer.setCallback(this);
		return enhancer.create();
	}
	
	@Override
	public Object intercept(Object arg0, Method method, Object[] arg2,
			MethodProxy arg3) throws Throwable {
		System.out.println("I am the data operation before modification------");
		Object invoke = arg3.invokeSuper(arg0, arg2);//And the following two methods can be
		//Object invoke = arg3.invoke(o, arg2);
		//Object invoke = method.invoke(o, arg2);
		System.out.println("I am the data operation after the call======");
		return invoke;
	}
}
The Enhancer here is a bytecode enhancer of CGLIB, which can easily extend the class you want to process;

The two commented out calls under the intercept method here are achievable, but the parameters are different, which is different from the JDK; but you can check the difference between the three calls by yourself.

package flex.cc.financialManagement.accountReceivable.web;

public class TestCglib {

	public static void main(String[] args) {
		TestCglibimpl a=new TestCglibimpl();
		CreatCglibModel b = new CreatCglibModel ();
		a = (TestCglibimpl) b.getObject(a);
		a.say();
	}
}

Test Results:

I am the data manipulation before modification------
I am CGLIB dynamic proxy!
I am the data manipulation after calling ======


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325592310&siteId=291194637