# spring-aop **Repository Path**: java-lesson/spring-aop ## Basic Information - **Project Name**: spring-aop - **Description**: No description available - **Primary Language**: Java - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-04-03 - **Last Updated**: 2026-04-03 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Spring AOP Demo Project ## Introduction This is a **beginner-friendly** Spring AOP demonstration project that shows how to use Spring AOP for method interception through a simple user management example. This project contains **only one logging aspect**, using the most common User entity and CRUD operations, allowing beginners to focus on understanding the core concepts of AOP while staying close to real-world scenarios. ### Core Technologies - **Spring Framework 7.0.0**: Latest version of Spring - **Spring AOP**: Spring's AOP implementation (included in spring-context) - **Spring Aspects**: Provides AspectJ annotation support - **AspectJ Weaver**: Runtime weaver for dynamically weaving aspect logic - **Maven**: Build and dependency management tool ### Business Scenarios The project simulates a simple user management system with basic operations: 1. **Create User** - Add new user 2. **Delete User** - Remove user 3. **Exception Handling** - Query non-existent user ### AOP Core Concepts This project demonstrates the following AOP concepts: 1. **Aspect**: Modularization of cross-cutting concerns (logging, transactions, security, etc.) 2. **JoinPoint**: A point during program execution, such as a method call 3. **Advice**: Action taken at a particular join point - Before Advice (@Before) - After Returning Advice (@AfterReturning) - After Throwing Advice (@AfterThrowing) - Around Advice (@Around) 4. **Pointcut**: Expression that matches join points where advice should be applied 5. **Weaving**: Process of applying aspects to target objects ### AOP Application Scenarios in Production | Scenario | Description | Typical Applications | Recommended Implementation | Scope Level | |----------|-------------|---------------------|----------------------------|-------------| | **Logging** | Log method calls, parameters, execution time | Operation audit, troubleshooting | @Around + Custom Annotation | Package / Class Level | | **Performance Monitoring** | Monitor method execution duration | Performance bottleneck identification, system optimization | @Around + ProceedingJoinPoint | Method Name Pattern / Annotation Level | | **Transaction Management** | Manage database transaction boundaries | Data consistency guarantee | @Transactional Annotation | Specific Method / Class Level | | **Authorization** | Check user roles and permissions | Resource access control, security protection | @Before + Custom Annotation | Annotation Level / Method Name Pattern | | **Caching** | Automatically cache query results | Improve system performance, reduce database pressure | @Around + Spring Cache | Annotation Level | | **Exception Handling** | Unified exception capture and handling | Global error handling, friendly prompts | @AfterThrowing + Global Exception Handler | Package / Class Level | **Scope Level Explanation**: - **Package Level**: `execution(* com.example.service..*.*(..))` - Matches all classes and methods under entire package - **Class Level**: `execution(* com.example.service.UserService.*(..))` - Matches all methods of a specific class - **Method Name Pattern**: `execution(* com.example.service.UserService.save*(..))` - Matches methods matching naming pattern - **Specific Method**: `execution(* com.example.service.UserService.getUserById(Long))` - Precisely matches a specific method - **Annotation Level**: `@annotation(com.example.LogExecutionTime)` - Matches methods with specific annotation **Real Project Example**: ```java // Performance monitoring aspect @Aspect @Component public class PerformanceMonitorAspect { @Around("@annotation(LogExecutionTime)") public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable { long start = System.currentTimeMillis(); Object result = joinPoint.proceed(); long duration = System.currentTimeMillis() - start; System.out.println("Method execution time: " + duration + "ms"); return result; } } // Use custom annotation @LogExecutionTime public User getUserById(Long id) { // Business logic } ``` ## Project Structure ``` spring-aop/ ├── pom.xml # Maven configuration ├── src/main/java/com/example/aop/ │ ├── Application.java # Main application entry │ ├── config/ │ │ └── AppConfig.java # Spring application configuration │ ├── service/ │ │ └── UserService.java # User service (business logic) │ ├── model/ │ │ └── User.java # User model │ └── aspect/ │ └── LoggingAspect.java # Logging aspect (the only one) ├── .gitignore # Git ignore configuration └── README.md # Project documentation ``` ## Installation ### Prerequisites - **JDK**: 17 or higher - **Maven**: 3.6 or higher ### Steps 1. **Clone or download the project** ```bash git clone cd spring-aop ``` 2. **Download dependencies with Maven** ```bash mvn clean install ``` Maven will automatically download all dependencies including `org.springframework:spring-aspects` 3. **Compile the project** ```bash mvn compile ``` ## Usage ### Option 1: Run with Maven ```bash mvn exec:java -Dexec.mainClass="com.example.aop.Application" ``` ### Option 2: Run packaged JAR ```bash # 1. Package the project mvn package # 2. Run the generated JAR file java -jar target/spring-aop-demo-1.0-SNAPSHOT.jar ``` ### Option 3: Run in IDE 1. Import the Maven project into IntelliJ IDEA or Eclipse 2. Locate `Application.java` 3. Right-click and run the main method ### Expected Output When running the program, you'll see output similar to this, demonstrating the logging aspect execution: ``` ======================================== Spring AOP Demo Application ======================================== [Test 1] Create New User ────────────────────────────────────── [LOG] ===== Method Call Start ===== [LOG] Class: com.example.aop.service.UserService [LOG] Method: createUser [LOG] Arguments: [赵六,35] [LOG] ============================= === [UserService] Creating user, Name: 赵六,Age: 35 === [UserService] User created successfully, ID: 4 [LOG] ✓ Method 'createUser' executed successfully [LOG] Return type: User Create success: User{id=4, name='赵六', age=35} [Test 2] Delete User ID: 3 ────────────────────────────────────── [LOG] ===== Method Call Start ===== ... ``` ## Code Explanation ### Main Classes #### 1. **User** - User Model Simple POJO with fields: - `id` - User ID - `name` - Name - `age` - Age #### 2. **UserService** - User Service Business methods: - `getUserById()` - Get user by ID (for exception demo) - `createUser()` - Create new user - `deleteUser()` - Delete user #### 3. **LoggingAspect** - Logging Aspect (The Only One) Features: - Logs all UserService method calls - Records method parameters and return values - Logs exception information Use case: Production audit, troubleshooting #### 4. **AppConfig** - Application Configuration Class Features: - Enables AspectJ auto-proxying - Scans component packages #### 5. **Application** - Main Program Demonstrates 3 test scenarios: 1. Create new user 2. Delete user ID: 3 3. Exception handling: Get non-existent user ## Contributing 1. Fork this repository 2. Create a new Feat_xxx branch 3. Commit your changes 4. Create a new Pull Request ## Learning Resources - [Spring Official Documentation - AOP](https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#aop) - [AspectJ Programming Guide](https://www.eclipse.org/aspectj/doc/released/progguide/index.html) - [Spring AOP vs AspectJ](https://www.baeldung.com/spring-aop-vs-aspectj) ## FAQ ### Q1: Why is there only one logging aspect? A: This is a **beginner-friendly** project designed to help learners focus on understanding the core concepts of AOP without being distracted by the complex interactions of multiple aspects. Once you've mastered the basics of AOP, you can extend with more practical aspects: - Performance monitoring aspect - Transaction management aspect - Authorization aspect - Caching aspect ### Q2: Can the spring-aop dependency be removed? A: This is a classic Maven dependency management question with two perspectives: **Perspective 1: Explicit Declaration (Recommended for Production)** ✅ Although `spring-context` already includes `spring-aop`, explicit declaration has these benefits: 1. **Clear Intent**: Clearly states that the project explicitly depends on spring-aop, not accidentally using it 2. **Change Resistance**: Even if spring-context removes this dependency in the future, the project won't be affected 3. **Version Control**: Can independently control spring-aop version (upgrade or downgrade) 4. **Easy Auditing**: New team members can understand complete dependencies by reading pom.xml **Perspective 2: Transitive Dependency is Sufficient (For Simple Projects)** Only declare `spring-context` and let `spring-aop` be automatically introduced as a transitive dependency. This is concise but has implicit dependency risks. **This Project's Choice**: We adopt **Perspective 1** and explicitly declare the `spring-aop` dependency. This is best practice for production projects and avoids potential future dependency risks. **Verification Method**: ```bash # View full dependency tree mvn dependency:tree # You'll see spring-aop is both transitively included via spring-context # and directly included via explicit declaration ``` ### Q3: What's the relationship between spring-aspects and aspectjweaver? A: - **spring-aspects**: Provides Spring support for AspectJ annotations (like `@Aspect`, `@Before`, etc.) - **aspectjweaver**: AspectJ's weaver, responsible for weaving aspect logic into target objects at runtime - **Both are required when using @Aspect annotations** and cannot be removed ### Q4: Why is my aspect not working? A: Check the following: 1. Ensure the aspect class has both `@Aspect` and `@Component` annotations 2. Ensure the configuration class has `@EnableAspectJAutoProxy` 3. Verify the pointcut expression correctly matches target methods 4. Make sure you're getting the Bean from Spring container, not using `new` ### Q5: What's the difference between JDK Dynamic Proxy and CGLIB? A: - **JDK Dynamic Proxy**: Can only proxy classes that implement interfaces, proxy based on interface - **CGLIB**: Can proxy classes without interfaces, proxy based on subclassing - Spring Boot 2.x+ uses CGLIB by default ### Q6: How to use AOP in production? A: Refer to the "AOP Application Scenarios in Production" table above and choose the appropriate aspect type based on your needs. Key points: 1. **Identify Cross-Cutting Concerns**: Recognize which functionalities span multiple modules (e.g., logging, security) 2. **Choose Appropriate Advice Type**: - Pre-processing only → `@Before` - Need return value → `@AfterReturning` - Need exception handling → `@AfterThrowing` - Need full control → `@Around` (most powerful, but highest performance overhead) 3. **Define Clear Pointcuts**: Use execution or annotation approach 4. **Avoid Overuse**: While AOP is powerful, overuse can increase code comprehension difficulty