Java implements a simple interceptor operation through dynamic proxies

  • 2021-10-25 06:45:36
  • OfStack

1. Agents

Before using dynamic proxies to implement interceptors, let's have a brief look at what Java proxies are.

Proxy, as its name implies, does not directly manipulate the proxy object (hereinafter referred to as the target object, which sounds comfortable), but indirectly uses the methods in the target object through a proxy object. Proxy is divided into two modes, one is static proxy and the other is dynamic proxy. Next, write an example of a static proxy.

Whether it is a static proxy or a dynamic proxy, the target object (target) must implement an interface (interface). Note that if you use the proxy provided by cglib, you don't have to implement the interface, but implement it through subclasses, so this method will not be discussed for the time being.

(1) Define an interface first


public interface IUserDao {
    void save();
}

(2) Define the target object (target)


public class UserDaoImpl implements IUserDao {
    public void save() {
        System.out.println("-------- Data has been saved ---------");
    }
}

(3) Define proxy objects


public class UserDaoProxy implements IUserDao {
 private IUserDao target;// Place the target object in the proxy object 
 public UserDaoProxy(IUserDao target){
  this.target = target;
  }
 public void save() {
     System.out.println("------ Start a transaction ------");
            target.save();
     System.out.println("------- Commit transaction ------");
    }
}

Under Test 1:


public class Test {
public static void main(String[] args){
    IUserDao userDao = new UserDaoImpl();
    UserDaoProxy proxy = new UserDaoProxy(userDao);
    proxy.save();// Called through a proxy object save Method 
    }
}

The output is:

--Start business--
------------

--Submission of business--

One problem with this approach is that the proxy object must also implement the same interface implemented by the proxy object, which leads to serious coupling. Therefore, one improved method is used below, that is, dynamic proxy (jdk proxy).

Dynamic proxy also requires the target object (target) to implement an interface

(1) Define an interface (IUserDao)

(2) Define a target object class (UserDaoImpl)

(3) Create a dynamic proxy class


public class ProxyFactory {
    // Maintenance 1 Target objects 
    private Object target; 
    public ProxyFactory(Object target) {
        this.target = target;
    }
 
    // Generate a proxy object for the target object 
    public Object getProxyInstance() {
        System.out.println("----target class---" + target.getClass());
        System.out.println("----target interfaces---" +
            target.getClass().getInterfaces());
 
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            new InvocationHandler() {
                public Object invoke(Object proxy, Method method, Object[] args)
                    throws Throwable {
                    System.out.println("---- Start a transaction 2-----");
 
                    // Execute the target object method 
                    Object returnValue = method.invoke(target, args);
                    System.out.println("---- Commit transaction 2----");
 
                    return returnValue;
                }
            });
    }
}

Under Test 1:


public class Test {
    public static void main(String[] args) {
        // Target object 
        IUserDao target = new UserDao();
        System.out.println(target.getClass());
 
        // Create a proxy object for the target object 
        IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance();
        System.out.println("----proxy---- : " + proxy.getClass());
        proxy.save();
        proxy.delete();
    }
}

Output:

class com.jd.pattern.proxy.dynamicProxy.UserDao
----target class---class com.jd.pattern.proxy.dynamicProxy.UserDao
----target interfaces---[Ljava.lang.Class;@1fb3ebeb
--proxy--: class com. sun. proxy. $Proxy0
--Start business 2---
--Save complete---
Commit transaction 2--
--Start business 2---
--Deletion complete--

Commit transaction 2--

2. Implement a simple interceptor using a dynamic proxy

Since the dynamic proxy is used, there must be an interface, a target class, a proxy class, and an interceptor

1. Define an interface


public interface BusinessFacade {
    void doSomething();
}

2. Define a target object


public class BusinessClass implements BusinessFacade {
    public void doSomething() {
        System.out.println(" In the business component BusinessClass Call in doSomething Method ");
    }
}

3. Create an interceptor


public class InterceptorClass {
    public void before() {
        System.out.println(" In InterceptorClass Invoke the method in: before()");
    }
 
    public void after() {
        System.out.println(" In InterceptorClass Invoke the method in: after()");
    }
}

4. Create an agent


public class DynamicProxyHandler {
    // Declare a proxy object 
    private Object target;
    // Create an interceptor 
    InterceptorClass interceptor = new InterceptorClass();
    // Dynamic generation 1 Proxy objects, and bound to the proxy class and proxy handler 
    public Object getProxyInstance(final Object target) {
        this.target = target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            new InvocationHandler() {
                public Object invoke(Object proxy, Method method, Object[] args)
                    throws Throwable {
                    interceptor.before();
                    Object result = method.invoke(target, args);
                    interceptor.after();
                    return result;
                }
            });
    }
}

Under Test 1:


public class UserDaoImpl implements IUserDao {
    public void save() {
        System.out.println("-------- Data has been saved ---------");
    }
}
0

Output:

Invoke method in InterceptorClass: before ()
Call the doSomething method in the business component BusinessClass
Invoke method in InterceptorClass: after ()


Related articles: