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
<dependency> <groupId></groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <dependency> <groupId></groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.0</version> <!-- Select version as needed --> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency>
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<UserMapper, User> { 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<User> { // 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.