1. Basic Concepts

  • AOP, namely, section-oriented programming, uses AOP to isolate each part of business logic, thus reducing the degree of coupling between each part of business logic, improving the reusability of programs, and improving the efficiency of development
  • You can clearly define where and how this functionality is applied without having to modify the affected classes. In this way, crosscutting concerns are modularized into special classes — classes commonly referred to as “facets.”
  • That is, adding new functionality to the trunk functionality without modifying the source code
  • The benefits of AOP:
    • Everything logic in one location, code is not scattered, easy to maintain and upgrade
    • The business module is more concise and contains only the core business code

Second, the underlying principle

  • AOP uses dynamic proxies at the bottom, and in the case of interfaces, JDK dynamic proxies; In the absence of an interface, the CGLIB proxy is used. For specific design patterns, see proxy patterns

AOP terminology

  • Crosscutting concerns: The same class of non-core business extracted from each method.
  • Aspect: A class that encapsulates information about crosscutting concerns, each of which is represented as a notification method.
  • Advice: The specific work that must be done by the aspect
  • Target: The notified object
  • Proxy: A Proxy object created after notification is applied to the target object
  • Joinpoint: crosscutting concerns are embodied in program code, corresponding to a specific point in program execution. For example, before or after a class method is called, or after the method catches an exception.

In an application, you can use horizontal and vertical coordinates to locate a specific join point:

  • Pointcut: A way of locating join points. Each class has multiple join points in its methods, so join points are an objective thing in a class. If you think of join points as records in a database, pointcuts are query criteria — AOP can use pointcuts to locate specific join points. Point of contact throughorg.springframework.aop.PointcutInterfaces are described using classes and methods as query criteria for join points.
  • Simply put, crosscutting concerns are the extracted business, facets are the classes that encapsulate the business methods, and notifications are concrete methods. Each target has a corresponding crosscutting concern. The specific position in the program is the join point, and the join point can choose whether to cut into the notification or not.

4. AOP dependency

  • The Spring framework generally implements AOP operations based on AspectJ
  • Related dependencies:

  • Or import via Maven
 <dependencies>
<! Spring AOP package -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>5.2.10. RELEASE</version>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>5.2.10. RELEASE</version>
</dependency>

<! - springIOC package -- -- >
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>5.2.10. RELEASE</version>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.10. RELEASE</version>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>5.2.10. RELEASE</version>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-beans</artifactId>
    <version>5.2.10. RELEASE</version>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-expression</artifactId>
    <version>5.2.10. RELEASE</version>
</dependency>
</dependencies>
Copy the code

5. Based on annotations

  • In the Spring configuration file, turn on annotation scanning, turn on AOP
    
            
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
    Copy the code
    <! -- Enable annotation scan -->
    <context:component-scan base-package="com.du.spring5"/>
    Copy the code
  • The proxy object generation function is enabled
    <! -- Enable proxy object generation -->
    <aop:aspectj-autoproxy/>
    Copy the code
  • Through annotation@ComponentcreateUserProxyObject added on top of the enhanced class@Aspect, indicating that this is a facet object
    @Component
    @Aspect
    public class UserProxy2 {... }Copy the code
  • Configure different types of notification. Add notification type annotations as notification methods, configured using pointcut expressions.
  • AspectJ supports five types of notification annotations:
    • @Before: pre-notification, executed before method execution
    • @After: post-notification, executed after method execution
    • @AfterRunning: returns a notification, executed after the method returns the result
    • @AfterThrowing: exception notification, executed after the method throws an exception
    • @Around: Surrounds the notification, executed around the method
  • Add another one to the cut surface@OrderNote, you can set the priority of multiple sections, the smaller the value, the higher the priority, the earlier the operation
    @Component // Configure through annotations
    @Aspect // Generate a proxy object
    @Order(10)
    public class UserProxy {}Copy the code

Pointcut expressions

  • Know which methods in which classes to enhance
  • Grammatical structure:Execution ([permission modifier] [return type] [class full path] [method name]([parameter list]))

6.1 example

  • rightcom.du.spring5.bean.UserThe inside of the classaddTo enhance:execution(* com.du.spring5.bean.User.add(..) )
  • rightcom.du.spring5.bean.UserAll methods in the class are enhanced:execution(* com.du.spring5.bean.User.*(..) )
  • rightcom.du.spring5.beanAll methods of all classes in the package are enhanced:execution(* com.du.spring5.bean.*.*(..) )
  • .Matches any number of parameters of any type

6.2 example 2

  • In AspectJ, point expression can pass “&”, “| |”, “!” And so on.
  • Add or sub methods in any class whose first argument is int:execution (* *.add(int,..) ) || execution(* *.sub(int,..) )

7. Advice

  • The operation to be performed at a specific join point
  • A section can contain one or more notifications.
  • The value of the annotation used for advice is often a pointcut expression.

7.1 Pre-Notification

  • Notification executed before method execution
  • use@Beforeannotations

7.2 Post Notification

  • Post-notification: Post-notification is executed after the join point has completed, after the join point has returned a result or thrown an exception. The analogy is finally, which executes whether or not it ends properly.
  • use@Afterannotations

7.3 Notification Return

  • Only when the normal end, will be executed
  • use@AfterReturningannotations
  • If you want to get the result of the method after it has executed, you can add a receive to the parameter listresultThe following is an example:
@AfterReturning(value = "execution(* com.du.spring5.bean.*.*(..) )", returning = "result")
  public void afterReturning(Object result) {
    System.out.println("Method completes execution and returns value" + result);
  }
Copy the code

Returning specifies to which parameter the return value is assigned, and the parameter name result is assigned to it

7.4 Exception Notification

  • Exception notification is performed only when the join point throws an exception
  • use@AfterThrowingannotations
  • To catch information about the exception, you can add an accept to the input parameter as aboveException“, and annotated
  @AfterThrowing(value = "execution(* com.du.spring5.bean.*.*(..) )", throwing = "exception")
  public void afterThrowing(Exception exception) {
    System.out.println("It happened." + exception + "Abnormal");
  }
Copy the code

7.5 JoinPoint

  • If you want to receive information about the target method in the notification, you can add one to the parameter listJoinPointType, which Spring will automatically inject into the method without specifying it in annotations.
  @Before(value = "execution(* com.du.spring5.bean.*.*(..) )"
  public void before(JoinPoint joinPoint) {
    // Get all the input parameters of the method
    Object[] args = joinPoint.getArgs();
    // Get the signature
    Signature signature = joinPoint.getSignature();
    System.out.println("In execution [" + signature.getName() + "] method with parameter" + Arrays.toString(args));
  }
Copy the code

For more details, see JoinPoint Interface

7.6 the @pointcut

  • To avoid repeating pointcut expressions, annotations can be used@Pointcut, unified configuration, unified use.
      @Pointcut("execution(* com.du.spring5.bean.*.*(..) )"
      public void pointcut(a) {}@Before(value = "pointcut()")
      public void before(JoinPoint joinPoint) {}Copy the code

7.7 Surround Notification

  • Wraparound advice is the most powerful of all notification types, giving you complete control over join points and even whether they are executed.
  • Much like a reflection method, it is equivalent to receiving an object containing the method to be executed and its parameters in the parameterProceedingJoinPoint, and then executes the method through the reflection method. Around the execution method, you can add sometry-catch-finallyTo achieve the same effect as the above four notification types.
      @Around(value="pointcut()")
      public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        try {
          System.out.println([Surround pre-notification]);
          
          Object[] args = joinPoint.getArgs(); // Get parameters
          Object res = joinPoint.proceed(args);  // Execute the method to get the result
          
          System.out.println("[circular return notification], result is" + res);
          return res;
        } catch (Throwable throwable) {
          System.out.println("[Surround exception Notification]");
          throw new RuntimeException(throwable);
        } finally {
          System.out.println("[Surround back notification]"); }}Copy the code

    Remember to return the received result, otherwise the annotated @AfterRETURNING method, where the method was actually called, will not be able to retrieve the result of its execution.

    interceptedExceptionRemember to throw it, too, or else it won’t be picked up anywhere else.

7.8 Execution Sequence

  • The current version is5.2.10The execution sequence is as follows
  • No exception:@Before-> The real way ->@AfterReturning -> @After
  • Exceptions exist:@Before-> The real way ->@AfterThrowing -> @After
  • After including the above wrap notification:Surround front notification -> @Before-> The real way ->@AfterReturning -> @After -> Circular return notification -> Surround the rear notification

Full annotation development

  • Instead of using an XML file, use a Config class directly
@Configuration // indicates this is a configuration class
@ComponentScan(basePackages = {"com.du.spring5"})  // Enable component scanning
@EnableAspectJAutoProxy(proxyTargetClass = true)  / / open the aop
public class ConfigAop {}Copy the code
  • call
  @Test
  public void test3(a) {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigAop.class);  / / configuration class
    User2 user2 = context.getBean("user2", User2.class);
    user2.add();
  }
Copy the code

9. Based on XML files

  • In addition to declaring aspects using AspectJ annotations, Spring also supports declaring aspects in bean configuration files. This declaration is done through XML elements in the AOP namespace.
  • Normally, annotation-based declarations take precedence over XML-based declarations. Aspects are aspectJ-compliant through AspectJ annotations, and XML-based configuration is proprietary to Spring. As AspectJ is increasingly supported by AOP frameworks, there will be more opportunities for reuse of aspects written in an annotated style.
  • Comparison: More important configurations passxmlConfiguration; Other configurations are configured through annotations.

9.1 Configuration Cases

  • XML file, namespace to add AOP related content
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"
    >
    Copy the code
  • Configure AOP on XML
    • In the Bean configuration file, all Spring AOP configurations must be defined in<aop:config>Inside the element. For each facet, create one<aop:aspect>Element to reference a back-end bean instance for a specific aspect implementation.
    • The aspect bean must have an identifier for<aop:aspect>Element references.
    <aop:config>
        <! Set pointcut -->
        <aop:pointcut id="user_add_pointcut" expression="execution(* com.du.spring5.bean.User.add(..) )"/>
        <! -- Set section -->
        <aop:aspect ref="userProxy">
            <! -- Set the position of the cut and use the method of the cut insert.
            <! Method = method; pointcut-ref = pointcut;
            <aop:before method="before" pointcut-ref="user_add_pointcut"/>
            <aop:after method="after" pointcut-ref="user_add_pointcut"/>
            <aop:after-returning method="afterReturn" pointcut-ref="user_add_pointcut"/>
            <aop:after-throwing method="afterThrowing" pointcut-ref="user_add_pointcut"/>
            <aop:around method="around" pointcut-ref="user_add_pointcut"/>
        </aop:aspect>
    </aop:config>
    Copy the code
  • Original class
    public class User {
      private final static Logger logger = Logger.getLogger(User.class);
      public void add(a) {
        logger.info("add......."); }}Copy the code
  • The proxy class
    public class UserProxy {
      private final static Logger logger = Logger.getLogger(UserProxy.class);
      /** ** */
      public void before(a) {
        logger.info("before");
      }
      /** * Final notification */
      public void after(a) {
        logger.info("after");
      }
      /** * return notification */
      public void afterReturn(a) {
        logger.info("afterReturn");
      }
      /** * Exception notification */
      public void afterThrowing(a) {
        logger.info("afterThrowing");
      }
      /** * surround notification *@param proceedingJoinPoint
       * @throws Throwable
       */
      public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        logger.info("around before");
        proceedingJoinPoint.proceed();
        logger.info("around ater"); }}Copy the code

9.2 configuration

  • All Spring AOP configurations must be defined in<aop:config>Inside the element. In this config, pass the desired section class<aop:aspect>Configuration.

Section 9.3

  • <aop:aspect>The section needs to specify which section class (already injected into the IOC container) is passedrefParameter specifies the object ID; You can also specify prioritiesorder

9.3 point

  • Pointcut usage<aop:pointcut>The element declaration
  • This tag can go in<aop:config>Inside, for all facets, you can put it in<aop:aspect>Use only for the current section.
  • The label needs to passexpressionSpecify pointcut expression, setidFor other tags to call.

9.4 Declaration Notice

  • beforeNotifications can be sent through<aop:before>The tag specifies, where,methodProperty specifies the method,pointcut-refSpecify pointcuts.
  • Specific configuration
<aop:config>
<! Set pointcut -->
<aop:pointcut id="user_add_pointcut" expression="execution(* com.du.spring5.bean.User.add(..) )"/>
<! -- Set section -->
<aop:aspect ref="userProxy">
    <! -- Set the position of the cut and use the method of the cut insert.
    <! Method = method; pointcut-ref = method;
    <aop:before method="before" pointcut-ref="user_add_pointcut"/>
    <aop:after method="after" pointcut-ref="user_add_pointcut"/>
    <aop:after-returning method="afterReturn" pointcut-ref="user_add_pointcut"/>
    <aop:after-throwing method="afterThrowing" pointcut-ref="user_add_pointcut"/>
    <aop:around method="around" pointcut-ref="user_add_pointcut"/>
</aop:aspect>
</aop:config>
Copy the code