SoFunction
Updated on 2025-03-03

SpringBoot integrates Aop

What can AOP do?

  • 1. Logging
  • Automatically record information such as method calls, parameters, return values ​​and exceptions, reducing the need to add log code to each method.
  • 2. Manage transactions
  • Automatically handle transactions opening, committing and rolling back before and after method execution to ensure data consistency and integrity.
  • 3. Permission control
  • Implement access control of the method, check user permissions, and ensure that only authorized users can perform specific operations.
  • 4. Performance monitoring
  • Automatically collect performance indicators such as the execution time and number of calls of the method to help developers perform performance analysis and optimization.
  • 5. Cache Management
  • Implement the cache of method results, reduce duplicate calculations, and improve system performance.
  • 6. Exception handling
  • Unify the exceptions in the execution of methods, simplify the exception capture and processing logic.
  • 7. Enter verification
  • Verify the input parameters before the method is executed to ensure the validity and integrity of the data.
  • 8. Dynamic Agent
  • Create proxy objects and add additional behavior without modifying the original class.

Application scenarios

  • Web Development: used for request processing, transaction management, security control, etc.
  • Enterprise Applications: Implement unified log and exception handling at the service layer.
  • Microservices: Perform unified monitoring and circuit breaking between services.

Logging

1. Preparation

First, you need to import AOP dependencies

<dependency>
    <groupId></groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
    <groupId>.fastjson2</groupId>
    <artifactId>fastjson2</artifactId>
    <version>2.0.50</version>
</dependency>
<dependency>
    <groupId></groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

Then you need to create a logging database and entity class and implement the insert data method in the Mapper layer

  • Entity Class
//Operation log entity class@Data
@NoArgsConstructor
@AllArgsConstructor
public class OperateLog {
    private Integer id; //Primary key ID    private Integer operateUser; //Operator ID    private LocalDateTime operateTime; //Operation time    private String className; //Operation class name    private String methodName; //Operation method name    private String methodParams; //Operation method parameters    private String returnValue; //Operation method return value    private Long costTime; //Time-consuming operation}
  • Mapper interface
@Mapper
public interface OperateLogMapper {

    //Insert log data    @Insert("insert into operate_log (operate_user, operate_time, class_name, method_name, method_params, return_value, cost_time) " +
            "values (#{operateUser}, #{operateTime}, #{className}, #{methodName}, #{methodParams}, #{returnValue}, #{costTime});")
    public void insert(OperateLog log);

}

2. Create custom annotations and facet classes

Because the operation log we want to record is the addition, deletion, and modification of data, @annotation is used to specify the method to be the connection point.

And in fields that consume time, the @Around notification type needs to be used.

  • Custom annotation class
@Retention()//Effective at runtime@Target()//It works in the methodpublic @interface Log {
}

3. Implement logging (Around)

First, add @Log annotation before the operation interface method that needs to be recorded

Next, implement operation logging in the facet class:

@Aspect
@Component
public class LogAsper {
    @Autowired
    private OperateLogMapper operateLogMapper;
    @Autowired
    private HttpServletRequest request;

    @Around("@annotation()")//Match the method of adding log annotation    public Object recordLog(ProceedingJoinPoint joinPoint) throws Throwable {
        OperateLog operateLog = new OperateLog();
        //Get the operator id, by obtaining and parsing the jwt token        String jwt = ("token");
        Claims claims = ((jwt));
        Integer operateUser =(Integer) ("id");
        (operateUser);
        //Get the operation time        (());
        //Get the operation class name        (().getClass().getName());
        //Get the operation method name        (().getName());
        //Get operation method parameters        ((()));
        //Get the start time        long begin = ();
        //Get the return value of the operation method        Object result = ();
        String returnValue = (result);
        (());
        //Get the operation end time        long end = ();
        //Time to obtain the operation        ((end-begin));
        (operateLog);
        return  result;

    }
}

Manage transactions

1. Add dependencies

Add MyBatis-Plus and AOP dependencies in

&lt;dependency&gt;
    &lt;groupId&gt;&lt;/groupId&gt;
    &lt;artifactId&gt;spring-boot-starter-aop&lt;/artifactId&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
    &lt;groupId&gt;&lt;/groupId&gt;
    &lt;artifactId&gt;mybatis-plus-boot-starter&lt;/artifactId&gt;
    &lt;version&gt;3.5.0&lt;/version&gt; &lt;!-- Select version as needed --&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
    &lt;groupId&gt;mysql&lt;/groupId&gt;
    &lt;artifactId&gt;mysql-connector-java&lt;/artifactId&gt;
    &lt;scope&gt;runtime&lt;/scope&gt;
&lt;/dependency&gt;

2. Configure MyBatis-Plus

Configure MyBatis-Plus and data sources in:

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/your_database
    username: your_username
    password: your_password
    driver-class-name: 
  mybatis-plus:
    mapper-locations: classpath*:/mappers/**/*.xml

3. Create transaction facets

Create a transaction facet class:

import ;
import ;
import ;
import ;
import ;

@Aspect
@Component
public class TransactionAspect {

    @Transactional
    @Around("execution(* ..*(..))") // Specify the business logic package that requires transactions    public Object manageTransaction(ProceedingJoinPoint joinPoint) throws Throwable {
        Object result;
        try {
            result = (); // Execute the target method            return result;
        } catch (Exception e) {
            throw e; // Throw an exception to trigger rollback        }
    }
}

4. Sample business logic class

Create a service class and use MyBatis-Plus to perform database operations:

import ;
import ;

@Service
public class UserService extends ServiceImpl&lt;UserMapper, User&gt; {

    public void createUser(User user) {
        (user); // Call MyBatis-Plus save method    }
}

5. User Entity and Mapper

  • Define user entities:
import ;
import ;

@TableName("users") // Database table namepublic class User {
    @TableId
    private Long id;
    private String name;

    // getters and setters
}
  • Mapper interface:
import ;

public interface UserMapper extends BaseMapper&lt;User&gt; {
    // Additional methods can be customized}

6. Create a controller

Call the createUser method of UserService in the controller:

import ;
import .*;

@RestController
@RequestMapping("/users")
public class UserController {

    @Autowired
    private UserService userService;

    @PostMapping
    public String createUser(@RequestBody User user) {
        (user); // Call the createUser method of UserService        return "User created successfully"; // Return a success message    }
}

7. Start class

import ;
import ;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        (, args);
    }
}

Experience

  • Through the above steps, you can integrate AOP and MyBatis-Plus in your Spring Boot project to achieve simple and effective transaction management.
  • In this way, whether it is committing a transaction under normal circumstances or rolling back a transaction when an exception occurs, it can be well supported.

Why do business, what's the use of doing business

  • Transactions ensure that a set of operations is either successful or all fails, thus maintaining the consistency and integrity of the data.
  • They are particularly important when handling bank transfers, order processing and other scenarios, and can prevent data loss caused by inconsistent data, partial updates, or system failures.
  • Through transactions, ensure that the data state remains reliable even in exceptional situations.

Then why do you need to combine AOP to do business

  • Combining AOP (sectional programming) can separate the logic of transaction management from business logic, improving the maintainability and readability of code.
  • Through AOP, transactions can be centrally managed, code structure can be simplified, and transactions can be automated, and duplicate codes can be reduced and development efficiency can be improved.

Permission control

1. Add dependencies

Add AOP-related dependencies in :

<dependency>
    <groupId></groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2. Create permission annotations

Define a custom annotation @RequiresPermission:

import ;
import ;
import ;
import ;

@Target()
@Retention()
public @interface RequiresPermission {
    String value();
}

3. Create a facet class

Create a tangent class, use the @Aspect annotation to define the tangent, and handle permission control logic:

import ;
import ;
import ;
import ;
import ;

@Component
@Aspect
public class PermissionAspect {

    @Autowired
    private UserService userService; // Obtain user services
    @Around("@annotation(requiresPermission)") // Intercept methods that use @RequiresPermission annotation    public Object checkPermission(ProceedingJoinPoint joinPoint, RequiresPermission requiresPermission) throws Throwable {
        String requiredPermission = (); // Get the required permissions
        // Permission check logic        if (!hasPermission(requiredPermission)) {
            throw new SecurityException("Permission denied: " + requiredPermission);
        }

        return (); // Execute the target method    }

    private boolean hasPermission(String permission) {
        User currentUser = (); // Get the current user
        if (currentUser == null) {
            return false; // The user is not logged in        }

        return ().contains(permission); // Check permissions    }
}

When using AOP, the @RequiresPermission annotation is a token that does not pass parameters directly on its own. Spring AOP automatically creates an instance of the annotation and passes it as a parameter to

checkPermission method. This is achieved through the AOP framework's proxy mechanism, not through explicit calls. Specifically, when the annotated method is called, AOP will intercept the call and inject the corresponding annotation information.

The permission parameter comes from the value() method annotated by @RequiresPermission. In the checkPermission method, when the method intercepts a method that uses the @RequiresPermission annotation, Spring AOP passes an instance of the annotation as a second parameter to the checkPermission method. Therefore, you can get the permission string defined in the annotation by calling ().

4. Use permission annotations

Use custom annotations on methods that require permission control

import ;
import ;

@RestController
public class MyController {

    @GetMapping("/admin")
    @RequiresPermission("ADMIN_ACCESS")
    public String adminAccess() {
        return "Welcome, admin!";
    }
}

5. Configure Spring Boot

Ensure that the Spring Boot application can scan to the facets and custom annotations. Normally, just add the @EnableAspectJAutoProxy annotation in the main class:

import ;
import ;
import ;

@SpringBootApplication
@EnableAspectJAutoProxy
public class MyApplication {
    public static void main(String[] args) {
        (, args);
    }
}

The purpose of @EnableAspectJAutoProxy annotation is to enable Spring's AOP (System-Oriented Programming) support, allowing the use of AspectJ's proxy mechanism to implement facets. Specifically, it has the following functions:

1.Enable proxy

It tells Spring to create proxy objects that intercept method calls and execute facet logic.

2. Support annotations

When you use annotations in your code (such as @Around, @Before, etc.), @EnableAspectJAutoProxy will make these annotations take effect, thereby enabling method interception and execution of facet logic.

3. Simplify configuration

By adding this annotation, developers do not need additional XML configuration, they only need to define the slicing and enhancement through the annotation, reducing the complexity of the configuration.

After adding this annotation to the main class, the Spring Boot application automatically scans the facet class and registers it to the application context, thus achieving the required AOP functionality.

The five notification types of AOP include

  • Pre-Notice (@Before)‌
  • Post-notification (@After)‌
  • Return Notification (@AfterReturning)‌
  • Exception notification (@AfterThrowing)‌
  • Surround notification (@Around)‌

Each notification type has its specific uses and scenarios, and can be selected and used according to actual needs.

Summarize

The above is personal experience. I hope you can give you a reference and I hope you can support me more.