concept
Talking about dynamic proxies brings to mind the powerful AOP capabilities of spring, the popular Java framework, which uses AOP to separate aspects from bodies, increasing the flexibility of programs. So what exactly is a dynamic proxy? Dynamic proxy, like reflection, is a dynamic feature of Java:
- You can create a class dynamically at run time that implements one or more interfaces
- It can dynamically add methods and modify behaviors for objects acquired by this class without modifying the original class, and is widely used in popular frameworks such as Spring and Mybatis
In Java, the equivalent of dynamic proxy is static proxy. Let’s first discuss what static proxy is
Static agent
Static proxy is a design pattern that usually has at least one real object behind it. Let’s look at an example:
public class SimpleStaticProxyDemo {
static interface IService{
public void sayHello(a);
}
// The proxied class
static class RealService implements IService{
@Override
public void sayHello(a) {
System.out.println("hello"); }}// The actual proxy class
static class TraceProxy implements IService{
// Let the proxied class have the function of the proxied class
private IService realService;
public TraceProxy(IService realService){
this.realService = realService;
}
@Override
public void sayHello(a) {
// Do not change the original program, and add new things, the same as below
System.out.println("Enter the sayHello");
realService.sayHello();
System.out.println("Leave sayHello"); }}public static void main(String[] args) {
// Instantiate the metaclass
IService realService = new RealService();
// Instantiate the proxy class
IService proxyService = newTraceProxy(realService); proxyService.sayHello(); }}Copy the code
The proxy and the real object will generally have the same interface: IService The real object: RealService the natural proxy is: TraceProxy and pass in the constructor the object of the proxied class
TraceProxy implements the function of RealService and adds the function of printing logs to it: system.out.println (” enter sayHello”); And system.out.println (” Leave sayHello”); And there are no changes to the existing classes. And finally, the TraceProxy object calls sayHello() to achieve the same function.
Program running results:
But this is actually troublesome, for example, we have many classes need to proxy, then need to write a proxy class for each class, which is not good, then dynamic proxy is born.
A dynamic proxy
Let’s look at an example of a dynamic proxy:
public class SimpleJDKDynamicproxyDemo {
static interface IService{
public void sayHello(a);
}
/ / the metaclass
static class RealService implements IService{
@Override
public void sayHello(a) {
System.out.println("hello"); }}/ / the proxy class
static class SimpleInvocationHandler implements InvocationHandler {
private Object realObj;
public SimpleInvocationHandler(Object realObj) {
this.realObj = realObj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Enter" + method.getName());
// Call the method corresponding to the actual object
Object result = method.invoke(realObj,args);
System.out.println("Left" + method.getName());
returnresult; }}public static void main(String[] args) {
// Instantiate the metaclass
IService realService = new RealService();
// Instantiate the proxy class
IService proxyService = (IService) Proxy.newProxyInstance(
IService.class.getClassLoader(),
newClass<? >[]{IService.class},newSimpleInvocationHandler(realService)); proxyService.sayHello(); }}Copy the code
Invoke invoke implements an interface called InvocationHandler (invoke). Invoke implements an interface called InvocationHandler (invoke). Invoke implements an interface called InvocationHandler (invoke).
- Proxy: indicates the proxy object itself, not the object being proxied. This parameter is not useful
- Method: indicates the method being invoked
- Args: indicates the parameters of the method
Unlike static proxies, proxy class objects are created in a different way
IService proxyService = (IService) Proxy.newProxyInstance(
IService.class.getClassLoader(),
newClass<? >[]{IService.class},new SimpleInvocationHandler(realService));
Copy the code
In the proxy.newProxyInstance () method, the parameter means:
- Loader: indicates the class loader
- Interface: indicates the list of interfaces to be implemented by the proxy. The element type must be interface, not common class
- H: Type InvocationHandler all method calls to the proxy interface are passed to this interface. Note that the implementation class of InvocationHandler, SimpleInvocationHandler, is passed
SayHello: proxyService sayHello: proxyService sayHello
Let’s explore the fundamentals of dynamic proxies
The basic principle of
In fact, the proxy object could be created like this:
// Create the proxy classClass<? > proxyClass = Proxy.getProxyClass(IService.class.getClassLoader(),newClass<? >[]{IService.class});// Get the proxy class parameter type is the constructor of InvocationHandlerConstructor<? > constructor = proxyClass.getConstructor(newClass<? >[]{InvocationHandler.class}); InvocationHandler handler =new SimpleInvocationHandler(realService);
// Instantiate the object through the constructor
IService proxyService = (IService) constructor.newInstance(handler);
proxyService.sayHello();
Copy the code
This class inherits Proxy and implements the Proxy interface Iservice. This class has a constructor that actually calls the constructor of the parent class whose parameter type is InvocationHandler. This proxy class implements the Iservice interface, so it can call the interface methods through its objects. How to call the interface methods?
SayHello is invoked by h.INvoke.(this, M3,null). This is actually the invoke method from the proxy class SimpleInvocationHandler in this example, so that it becomes clear.
Invoke (realObj,args); invoke(realObj,args); invoke(realObj,args) Actually call the method. The proxy class object also passes different parameters to Invoke when calling different methods.
The next article will explain the benefits of dynamic proxies and implement a simple AOP function