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