Implementation of AOP

  AOP (Aspect Orient Programming), which we generally call aspect-oriented (aspect) programming , as a supplement to object-oriented, is used to deal with cross-cutting concerns distributed in various modules in the system, such as transaction management, logging, caching, etc. .

  The key to AOP implementation lies in the AOP proxy automatically created by the AOP framework. AOP proxy is mainly divided into static proxy (compile-time enhancement) and dynamic proxy (run-time enhancement). The representative of the static proxy is AspectJ; while the dynamic proxy is represented by Spring AOP .

(1) Use AspectJ's compile-time enhancements to implement AOP

  The so-called static proxy is that the AOP framework generates AOP proxy classes during the compilation phase, so it is also called compile-time enhancement.

  As an example of an example. First we have a normal Hello class
  public class Hello {
    public void sayHello() {
      System.out.println("hello");
    }
    public static void main(String[] args) {
      Hello h = new Hello();
      h .sayHello();
    }
  }

 

  Use AspectJ to write an Aspect
    public aspect TxAspect {
      void around():call(void Hello.sayHello()){
        System.out.println("Start transaction...");
        proceed();
        System.out.println(" End of transaction...");
      }
     }

 

  After the compilation is complete, run the Hello class, you can see the following output
    Start the transaction...
    hello
    transaction ends...

 

  Obviously, AOP has taken effect, so how exactly does AspectJ achieve code enhancement without modifying the Hello class?
  Take a look at the compiled Hello.class
    public class Hello {
      public Hello() {
      }
      public void sayHello() {
        System.out.println("hello");
      }
      public static void main(String[] args) {
        Hello h = new Hello();
          sayHello_aroundBody1$advice(h, TxAspect.aspectOf(), (AroundClosure)null);
      }
    }

 

  In this way, the proceed() method is the callback to execute the method in the proxied class.

 

(2) Using Spring AOP

The dynamic proxy   used by Spring AOP , dynamic proxy means that AOP does not modify the bytecode, but temporarily generates an AOP object for the method in memory. This AOP object contains all the methods of the target object, and at a specific pointcut Enhanced processing is done and the method of the original object is called back. Two jar packages need to be imported: cglib.jar, asm.jar.

  There are two main ways of dynamic proxy in Spring AOP: jdk dynamic proxy and cglib dynamic proxy. The jdk dynamic proxy receives the proxied class through reflection , and requires that the proxied class must implement an interface. The core of jdk dynamic proxy is InvocationHandler interface  and Proxy class.

  When the target class does not implement the interface, Spring AOP will choose to use cglib to dynamically proxy the target class. cglib (Code Generation Library) is a code-generated class library that can dynamically generate subclasses of a class at runtime. cglib is a dynamic proxy through inheritance , so if a class is marked as final, then It cannot use cglib to do dynamic proxy.

  Define an interface
  public interface Person {
    String sayHello(String name);
  }

 

  实现类
  @Component
  public class Chinese implements Person {
    @Override
    public String sayHello(String name) {
      System.out.println("-- sayHello() --");
      return name + " hello, AOP";
    }
  }

   

  Implementation class

  public class MyInvocationHandler implements InvocationHandler {
     private Object target;
     MyInvocationHandler() {
      super();
    }
    MyInvocationHandler(Object target) {
      super();
      this.target = target;
    }
    public Object invoke(Object proxy, Method method, Object[] args ) throws Throwable {
      // Add logic before program execution, MethodBeforeAdviceInterceptor
      System.out.println("before----------------------------- ");
      // Program execution
      Object result = method.invoke(target, args);
      // Add logic after program execution, MethodAfterAdviceInterceptor
      System.out.println("after-------------- ----------------");
      return result;
    }
  }

 

  test class 

  public class Test {
  /**
  * JDK dynamic proxy test class
  */
  public static void main(String[] args) {
    Chinese chinese= new Chinese();
    MyInvocationHandler mih = new MyInvocationHandler(chinese);
    Class<?> cls = chinese .getClass();
    /**
    * loader class loader
    * interfaces implement interface
    * h InvocationHandler
    */
    Person p = (Person)Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), h);
    System.out .println(p.sayHello("Zhang San"));
    }
  }

 

  output

  before-----------------------------

  Zhang San hello, AOP

  after------------------------------

  

  Let's take a look at the case where the interface is not used, modify the Chinese class

  实现类
  @Component
  public class Chinese {
    public String sayHello(String name) {
      System.out.println("-- sayHello() --");
      return name + " hello, AOP";
    }
  }

   

  Implementation class 

  public class CglibProxy implements MethodInterceptor {
    public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable {
      System.out.println("before-------------");
      // 执行目标类add方法
      proxy.invokeSuper(object, args);
      System.out.println("after--------------");
      return null;
    }
  }

 

  Factory class of the target class

  public class Factory {
    //The enhanced target class, that is, the target class after adding the cut-in logic advice
    public static Base getInstance(CglibProxy proxy) {
      Enhancer enhancer = new Enhancer();
      enhancer.setSuperclass(Chinese.class);
      / /The parameter of the callback method is the proxy class object CglibProxy, and finally the enhanced target class calls the intercept method
      enhancer.setCallback(proxy) in the proxy class object CglibProxy;
      // At this moment, the base is not a pure target class, but an enhanced target Class
      Chinese chinese = (Chinese) enhancer.create();
      return chinese;
    }
  }

 

  test class  

  public class Test {
    public static void main(String[] args) {
      CglibProxy proxy = new CglibProxy();
      // base is the generated enhanced target class
      Chinese chinese = Factory.getInstance(proxy);
      System.out.println( chinese.sayHello("Zhang San"));
    }
  }

 

  output

  before-----------------------------

  Zhang San hello, AOP

  after------------------------------

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325674391&siteId=291194637