Java dynamic proxy classes can be divided into two types.
Static proxy: Created by programmers or automatically generates source code by specific tools and compiles it. Before the program runs, the .class file of the proxy class already exists.
Dynamic proxy: It is created dynamically using reflection mechanism when the program is running.
1. First, we will demonstrate the Java dynamic proxy.
Now we have a simple business interface Saying, as follows:
The code copy is as follows:
package testAOP;
public interface Saying {
public void saysHello(String name);
public void talking(String name);
}
A simple implementation class SayingImpl, as follows:
The code copy is as follows:
package testAOP;
public class SayingImpl implements Saying {
@Override
public void saysHello(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 must work hard to build a harmonious society!");
}
}
What we want to achieve is to dynamically implant the processing before and after sayingHello and talking.
JDK dynamic proxy mainly uses two classes in the java.lang.reflect package: Proxy and InvocationHandler.
InvocationHandler is an interface that defines cross-cutting logic by implementing this interface and calls the code of the target class through a reflection mechanism, dynamically weaves cross-cutting logic and business logic together.
Proxy uses InvocationHandler to dynamically create an instance that conforms to a certain interface and generates a proxy object of the target class.
As follows, we create an InvocationHandler instance:
The code copy is as follows:
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 {
//Execute before the target method
System.out.println("――――――――――――――――――――――――――");
System.out.println("Please speak on stage next person!");
//Target method call
Object obj = method.invoke(target, args);
//Execute the target method after
System.out.println("Everyone applause and encouragement!");
return obj;
}
}
Here is the test:
The code copy is as follows:
package testAOP;
import java.lang.reflect.Proxy;
public class JDKProxyTest {
public static void main(String[] args) {
// The target business category you want to be agented
Saying target = new SayingImpl();
// Weave the target class and the cross-cut class together
MyInvocationHandler handler = new MyInvocationHandler(target);
// Create a proxy instance
Saying proxy = (Saying) Proxy.newProxyInstance(
target.getClass().getClassLoader(), //The class loader of the target class
target.getClass().getInterfaces(), //Interfaces of the target class
handler);//cross-cut class
proxy.sayHello("Xiao Ming");
proxy.talking("Xiaoli");
}
}
The operation is as follows:
The code copy is as follows:
――――――――――――――――――――――――――
Please speak on stage next person!
Xiao Ming: Hello everyone!
Everyone applauded and encouraged!
――――――――――――――――――――――――――
Please speak on stage next person!
Xiaoli: I mean, we must work hard to build a harmonious society!
Everyone applauded and encouraged!
There is a big limitation to using JDK dynamic proxy, which is that it requires that the target class must implement the interface of the corresponding method, and it can only create proxy instances for the interface. We can see in the newProxyInstance method of Proxy in the test class above that the second parameter of this method is the interface of the target class. If this class does not implement an interface, it depends on cglib dynamic proxy.
CGLib adopts very underlying bytecode technology, which can create a subclass for a class, and use method intercepting techniques in the subclass to intercept all parent class methods calls, and implant cross-cutting logic in the situation.
2. Next, we will demonstrate the cglib dynamic proxy.
First of all, we need to guide the package. The package I use is cglib-nodep-2.1_3.jar.
We first create a proxy creator CglibProxy:
The code copy is as follows:
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 to be created
enhance.setSuperclass(clazz);
enhancer.setCallback(this);
// Dynamically create subclass instances through bytecode technology
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 speak on stage next person!");
//Target method call
Object result = proxy.invokeSuper(obj, args);
//Execute the target method after
System.out.println("Everyone applause and encouragement!");
return result;
}
}
Then test:
The code copy is as follows:
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 dynamically generating subclasses
Saying target = (Saying) proxy.getProxy(SayingImpl.class);
target.sayHello("Xiao Ming");
target.talking("Xiaoli");
}
}
The result is no different from the JDK dynamic proxy.
Both JDK dynamic proxy and CGLib dynamic proxy are runtime enhancements, which are enhanced by implanting cross-cut code into proxy classes. Unlike this, AspectJ, which can implant cross-cut code in the compilation period through a special compiler. Such enhanced processing is more advantageous at runtime, because JDK dynamic proxy and CGLib dynamic proxy are required every time they run. Enhanced.