Spring 6 [Method Parameter Verification, SpingAOP Introduction, Schema-based Way to Realize AOP] (14) - Comprehensive Detailed Explanation (Learning Summary --- From Introduction to Deepening)

 

Table of contents

4. Method parameter verification

Introduction to SpingAOP

Schema-based way to realize AOP 


4. Method parameter verification

The Spring framework provides a method for verifying method parameters. After calling a method to pass in parameters, it will determine whether the parameters meet the data verification. If the method is satisfied, the method is executed; if not: the method is not executed, and an exception is reported. This is not the same as above. And there is no need to use LocalValidatorFactoryBean.

The core of method parameter verification has three points:

1. The Bean MethodValidationPostProcessor must exist in the IoC container. None by default, we need to configure it manually

2. The @Validated annotation is required on the class that needs method verification

3. The method parameters that need to be verified need to be annotated with @Valid

4.1 Create a new class and add validation annotations 

We still use the Student class and add validation to the properties

@Data
public class Student {
   @NotBlank
   private String name;
   @Positive
   private int age;
}

4.2 Create a new class and add a method

Create a new com.tong.validation.StudentServiceImpl class and add annotations

@Validated // 重要
public class StudentServiceImpl{
    public void student(@Valid Student stu){// @Valid 重要
    System.out.println("执行了这个方法");
   }
}

 4.3 Create a new configuration file

Create a new configuration file applicationContext-methodvalidation.xml and configure Beans of MethodValidationPostProcessor and StudentServiceImpl in the configuration file. This function has nothing to do with LocalValidatorFactoryBean, and there is no need to configure the Bean of LocalValidatorFactoryBean.

<bean id="studentServiceImpl" class="com.tong.validation.StudentServiceImpl"></bean>

<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcess
or"></bean>

 4.4 Create a new test class

New com.tong.test.ValidationMethodTest test class

@SpringJUnitConfig
@ContextConfiguration("classpath:applicationContext-methodvalidation.xml")
public class ValidationMethodTest {
      @Autowired
      StudentServiceImpl studentService;
      
      @Test
      void test(){
           Student stu = new Student();
           studentService.student(stu);
     }
}

 4.5 Check the running effect

An exception is reported in the console.

jakarta.validation.ConstraintViolationException: student.arg0.age: 必须是正数,
student.arg0.name: 不能为空

4.6 Verification pass writing method

Set the upper value to the property of the Student object to pass the verification. After rerunning, it was found that the method was successfully called.

@SpringJUnitConfig
@ContextConfiguration("classpath:applicationContext-methodvalidation.xml")
public class ValidationMethodTest {
     @Autowired
     StudentServiceImpl studentService;
     @Test
     void test(){
         Student stu = new Student();
         stu.setName("smallming");//新加
         stu.setAge(16);// 新加
         studentService.student(stu);
    }
}

Introduction to SpingAOP

1. Introduction to Spring AOP

AOP (Aspect-oriented Programming, aspect-oriented programming) is not proposed by the Spring framework. It is a set of specifications organized by the AOP Alliance. Spring AOP is a specific implementation of the AOP specification. Let's first look at Spring's official explanation of Spring AOP.

Official description:

Translation meaning: 

Aspect-Oriented Programming (AOP) complements Object-Oriented Programming (OOP) by providing another way of thinking about program structure. The key unit of modularity in OOP is the class, while the unit of modularity in AOP is the aspect. Aspects enable the modularization of concerns (such as transaction management) across multiple types and objects. (Such concerns are often referred to as "crosscutting" concerns in the AOP literature.) One of the key components of Spring is the AOP frame. Although the Spring IoC container does not depend on AOP (meaning you don't need to use AOP if you don't want to), AOP complements Spring IoC to provide a very powerful middleware solution.

The following is a summary of the above official explanation: the official emphasized the following points when emphasizing AOP:

      1. AOP is called aspect-oriented programming

      2. AOP is a supplement to OOP

      3. The core of AOP is aspect

      4. AOP is dependent on IoC

      5. AOP allows multiple types and objects to form cross-sections in a modular manner. 

So the explanation of AOP: AOP is aspect-oriented programming. The method in the program can be extended , and the extension content and the target method are loosely coupled (no matter the target method or the client, after extension, they are unaware) and modularized. 

If you want to explain AOP clearly, you must clarify the technical terms in AOP.

 

Aspect: Aspect. Namely join point + Advice

join point: entry point. It is the target method we usually talk about, or which method to expand and enhance.

Advice: notification, enhanced content.

Pointcut: cut point. It is an expression, which means which methods are join point through the expression

AOP Proxy: Proxy. Spring supports JDK dynamic proxy and cglib dynamic proxy. You can modify the default JDK dynamic proxy to Cglib dynamic proxy through proxy-target-class=true.

Weaving: weaving into. Weaving is the process of adding Advice to the join point.

In actual development, AOP is mainly applied in the Service layer. 

 

Schema-based way to realize AOP 

1. Two ways to implement AOP

There are two ways to implement AOP in Spring:

  •       Schema-based: All notifications need to implement a specific type of interface.
  •       AspectJ: Advice can be implemented using normal Java classes combined with specific configuration tags.

No matter which method is used, two dependencies of spring-aop and aspectjweaver need to be imported in the project.

<dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-context</artifactId>
     <version>6.0.6</version>
</dependency>
<dependency>
     <groupId>org.aspectj</groupId>
     <artifactId>aspectjweaver</artifactId>
     <version>1.9.19</version>
</dependency>

 2. Classification of notifications in the Schema-based approach

  • Before Advice: An enhancement executed before the pointcut. Advice needs to implement the MethodBeforeAdvice interface
  • Post-advice: Enhancements executed after the pointcut. Advice needs to implement the AfterReturningAdvice interface
  • Surround Advice: A method that combines the functionality of pre-advice and post-advice. Notifications need to implement the MethodInterceptor interface
  • Exception notification: If an exception occurs in the entry point (absolutely not try...catch solves the exception), an exception notification will be triggered. Advice needs to implement the ThrowsAdvice interface.

3. Advance notice 

Before advice is an enhancement executed before the pointcut. In addition to ensuring the most basic environment dependencies of the Spring framework in the project, aspectj dependencies also need to be entered

<dependencies>
   <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>6.0.6</version>
   </dependency>
   <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.9.19</version>
   </dependency>
   <!-- 单元测试 -->
   <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>6.0.6</version>
   </dependency>
   <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-api</artifactId>
      <version>5.9.2</version>
      <scope>test</scope>
   </dependency>
   <!-- lombok 支持 @Data等注解 -->
   <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.26</version>
      <scope>provided</scope>
   </dependency>
</dependencies>

3.1 Create a new notification class

Create new com.bjsxt.advice.MyBefore.

The before method must be rewritten in the MethodBeforeAdvice interface, and there are three parameters in the method:

  • method: pointcut method object
  • args: pointcut method arguments
  • target: the object where the pointcut method is located
package com.tong.advice;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class MyBefore implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
          System.out.println("前置通知");
    }
}

3.2 Configuration aspect

<?xml version="1.0" encoding="UTF-8"?>
<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
       https://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop
       https://www.springframework.org/schema/aop/spring-aop.xsd">

    <context:component-scan base-package="com.tong.mapper,com.tong.service.impl"> 
    </context:component-scan>
    <bean id="mybefore" class="com.tong.advice.MyBefore"></bean>
      <aop:config>
      <!-- 切入点是固定语法:execution(* 方法的全限定路径带有参数) -->
      <!-- 无参方法:test()-->
      <!-- 有参方法:test(int,java.lang.String)-->
      <!-- 如果希望把所有叫做test的方法都匹配上,不考虑参数test(..)-->
      <!-- 全限定路径的层数绝对不能少,但是如果希望对类或包做统配使用*-->
      <!-- com.tong.service.impl.*.*(..)-->
        <aop:pointcut id="mypoint" expression="execution(* com.tong.service.impl.PeopleServiceImpl.test())"/>
       <aop:advisor advice-ref="mybefore" pointcut-ref="mypoint"></aop:advisor>
       </aop:config>
</beans>

4. Post notification

Post-advice is an enhancement that executes after the pointcut.

4.1 Create a new notification class

Create a new com.bjsxt.advice.MyAfter. The afterReturning method must be rewritten in the AfterReturningAdvice interface. There are four parameters in the method:

  • returnValue: return value
  • method: pointcut method object
  • args: pointcut method arguments
  • target: the object where the pointcut method is located
package com.tong.advice;
import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;
public class MyAfter implements AfterReturningAdvice {
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args,Object target) throws Throwable {
         System.out.println("后置通知");
     }
}

4.2 Configuration aspect

<?xml version="1.0" encoding="UTF-8"?>
<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
       https://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop
       https://www.springframework.org/schema/aop/spring-aop.xsd">

    <context:component-scan base-package="com.tong.mapper,com.tong.service.impl"> 
    </context:component-scan>
    <bean id="mybefore" class="com.tong.advice.MyBefore"></bean>
    <!-- 配置后置通知bean -->
    <bean id="myafter" class="com.tong.advice.MyAfter"></bean>
    <aop:config>
       <aop:pointcut id="mypoint" expression="execution(* com.tong.service.impl.PeopleServiceImpl.test())"/>
      <aop:advisor advice-ref="mybefore" pointcut-ref="mypoint"></aop:advisor>
      <!-- 织入后置通知 -->
      <aop:advisor advice-ref="myafter" pointcut-ref="mypoint"></aop:advisor>
    </aop:config>
</beans>

5. Surround notifications

Surround notification can realize both functions of pre-notification and post-notification.

5.1 Create a new notification class

Create a new com.tong.advice.MyAround.

The invoke method must be rewritten in the MethodInterceptor interface, and the parameters in the method are:

  • invocation: method invoker. The execution point can be called by the proceed() method through invocation. 
package com.tong.advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class MyAround implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
         System.out.println("环绕通知-前置增强");
         Object result = invocation.proceed();// 执行切入点
         System.out.println("环绕通知-后置增强");
         return result;
      }
}

 5.2 Configuration aspect

<?xml version="1.0" encoding="UTF-8"?>
<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
       https://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop
       https://www.springframework.org/schema/aop/spring-aop.xsd">

     <context:component-scan base-package="com.tong.mapper,com.tong.service.impl"> </context:component-scan>
     <bean id="mybefore" class="com.tong.advice.MyBefore"></bean>
     <bean id="myafter" class="com.tong.advice.MyAfter"></bean>
     <!-- 配置环绕通知bean -->
     <bean id="myaround" class="com.tong.advice.MyAround"></bean>
         <aop:config>
             <aop:pointcut id="mypoint" expression="execution(* com.tong.service.impl.PeopleServiceImpl.test())"/>
             <!-- 只织入环绕,没有织入前置通知和后置通知。 -->
             <aop:advisor advice-ref="myaround" pointcut-ref="mypoint"></aop:advisor>
         </aop:config>
</beans>

Guess you like

Origin blog.csdn.net/m0_58719994/article/details/132000739