Java dynamic proxy and cglib dynamic proxy examples are Shared
- 2020-04-01 03:12:51
- OfStack
There are two types of Java dynamic proxy classes.
Static proxy: source code is automatically generated and compiled by a programmer or by a specific tool. The.class file for the proxy class exists before the program runs.
Dynamic proxy: created dynamically using reflection while the program is running.
First, let's demonstrate Java dynamic proxy.
Now we have a simple business interface, Saying, as follows:
package testAOP;
public interface Saying {
public void sayHello(String name);
public void talking(String name);
}
A simple implementation class SayingImpl, as follows:
package testAOP;
public class SayingImpl implements Saying {
@Override
public void sayHello(String name) {
// TODO Auto-generated method stub
System.out.println(name + " : hello everyone! ");
}
@Override
public void talking(String name) {
// TODO Auto-generated method stub
System.out.println(name + " I mean, we should try our best to build a harmonious society! ");
}
}
What we're going to do is we're going to dynamically implant before and after sayHello and talking.
JDK dynamic Proxy mainly USES two classes in the java.lang.reflect package: Proxy and InvocationHandler.
The InvocationHandler is an interface that dynamically wearies together crosscutting logic and business logic by implementing an interface that defines crosscutting logic and invokes the target class's code through a reflection mechanism.
Proxy USES the InvocationHandler to dynamically create an instance that conforms to an interface and generates a Proxy object for the target class.
Here, we create an InvocationHandler instance:
package testAOP;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler {
private Object target;
MyInvocationHandler(Object target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//Target method before execution
System.out.println(" -- -- -- -- -- -- -- -- -- -- -- -- -- ");
System.out.println(" Please take the floor next! ");
//Target method call
Object obj = method.invoke(target, args);
//Target method after execution
System.out.println(" Everyone applaud! ");
return obj;
}
}
Here's the test:
package testAOP;
import java.lang.reflect.Proxy;
public class JDKProxyTest {
public static void main(String[] args) {
//The target business class that you want to be proxied to
Saying target = new SayingImpl();
//Weave the target and crosscutting classes together
MyInvocationHandler handler = new MyInvocationHandler(target);
//Create a proxy instance
Saying proxy = (Saying) Proxy.newProxyInstance(
target.getClass().getClassLoader(),//The class loader for the target class
target.getClass().getInterfaces(),//The interface of the target class
handler);//Crosscutting class
proxy.sayHello(" Xiao Ming ");
proxy.talking(" Small beautiful ");
}
}
The operation is as follows:
-- -- -- -- -- -- -- -- -- -- -- -- --
Please take the floor next!
Xiaoming: hello everyone!
Everyone applaud!
-- -- -- -- -- -- -- -- -- -- -- -- --
Please take the floor next!
Xiao li: I mean, we should try our best to build a harmonious society!
Everyone applaud!
One big limitation of using JDK dynamic proxy is that it requires the target class to implement the corresponding method's interface, and it can only create proxy instances for the interface. As you can see from the newProxyInstance method of the Proxy in the test class above, the second parameter of this method is the interface of the target class. If the class does not implement an interface, it is up to the cglib dynamic proxy.
CGLib USES a very low-level bytecode technique that allows you to create a subclass for a class, and in the subclass use the technique of method interception to intercept all calls to the parent class's methods, and then populate the crosscutting logic along the way.
Next, we will demonstrate the cglib dynamic proxy.
First we need the guide package, which I used is cglib-nodep-2.1_3.jar.
Let's first create a proxy creator CglibProxy:
package testAOP.cglib;
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 CglibProxy implements MethodInterceptor{
Enhancer enhancer = new Enhancer();
public Object getProxy(Class clazz) {
//Set the subclass you want to create
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
//Subclass instances are created dynamically by bytecode techniques
return enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
// TODO Auto-generated method stub
System.out.println(" -- -- -- -- -- -- -- -- -- -- -- -- -- ");
System.out.println(" Please take the floor next! ");
//Target method call
Object result = proxy.invokeSuper(obj, args);
//Target method after execution
System.out.println(" Everyone applaud! ");
return result;
}
}
Then test:
package testAOP.cglib;
import testAOP.Saying;
import testAOP.SayingImpl;
public class CglibProxyTest {
public static void main(String[] args) {
CglibProxy proxy = new CglibProxy();
//Create proxy classes by subclassing them dynamically
Saying target = (Saying) proxy.getProxy(SayingImpl.class);
target.sayHello(" Xiao Ming ");
target.talking(" Small beautiful ");
}
}
The result is no different from JDK dynamic proxies.
Both JDK dynamic proxy and CGLib dynamic proxy are runtime enhancements, enhanced by embedding cross-cutting code into proxy classes. Unlike AspectJ, which has the ability to embed crosscutting code with enhancements at compile time through a special compiler, such enhancements are more advantageous at run time because JDK dynamic proxies and CGLib dynamic proxies require enhancements every time they are run.