Detail Java Reflection to implement Aop agent

  • 2020-06-15 09:02:16
  • OfStack

Use reflection to generate a dynamic proxy for JDK, the AOP proxy in AOP, instead of the target object to weave enhancements into your code.

Defining the proxy interface

Since the JDKf dynamic proxy can only create dynamic proxy for the interface, the interface is defined first. Suppose we need to add transaction processing to the Save method of data. We have an UserDao interface, which contains an Save method.


public interface UserDao {
  public void save();
}

Defining the proxy implementation

Below to implement the interface definition of the Save method, we use the following code to implement.


public class UserDaoImpl implements UserDao {

  @Override
  public void save() {
    System.out.println("I am save user....");
  }

}

Define enhancement code

We have opened the transaction before saving the user, committed the transaction after saving the user, and defined in the enhancement code two methods, before() and after(), used before and after the execution of the save() method.


public class UserTx {
  public void before(){
    System.out.println("before save.....");
  }
  public void after(){
    System.out.println("after save......");
  }
}

Define Invocation handler

The reason for defining handler is that when we execute the dynamic proxy, we actually execute the invoke() method in handler, so we customize the content of the method in the invoke() method to achieve the proxy and enhanced logic and effect.


public class UserDaoInvocationHandler implements InvocationHandler {
  /
    Objects that require a proxy 
   /
  private Object proxyObj;
  /
    Specifies the object we want the proxy for 
   @param proxyObj
   */
  public void setProxyObj(Object proxyObj) {
    this.proxyObj = proxyObj;
  }
  @Override
  public Object invoke(Object proxy, Method method, Object[] args)
      throws Throwable {
    UserTx tx = new UserTx();
    tx.before();
    Object resultObj = method.invoke(proxyObj, args);
    tx.after();
    return resultObj;
  }
}

The test results

With everything defined above, we will actually dynamically proxy the object we specified, using the proxy object to execute the method we want to execute, and verify that the proxy is successful.


import java.lang.reflect.Proxy;
public class ProxyTst {
  public static void main(String[] args) {
    // proxy object
    UserDao target = new UserDaoImpl();
    // invocation handler
    UserDaoInvocationHandler handler = new UserDaoInvocationHandler();
    handler.setProxyObj(target);
    // proxy
    UserDao targeted = (UserDao) Proxy.newProxyInstance(
        target.getClass().getClassLoader(),
        target.getClass().getInterfaces(),
        handler);
    // execute proxyed object
    targeted.save();
  }
}

After executing the above code, we can see the following output in the console, indicating that UserDao has been successfully represented and that we have successfully added transaction functionality to our program.


before save.....
I am save user....
after save......

Related articles: