spring-aop
Spring AOP (Aspect-Oriented Programming) per Spring Boot 3.x. Copre @Aspect, pointcut expressions, @Around/@Before/@After advice, custom annotations, logging, security, caching, e transaction patterns. Usa per cross-cutting concerns. USE WHEN: user mentions "aspect", "AOP", "cross-cutting", "logging aspect", "pointcut", asks about "how to intercept methods", "apply logic to multiple methods", "@Around advice" DO NOT USE FOR: security configuration - use `spring-security` instead, transaction management - use `spring-data-jpa` instead
What this skill does
# Spring AOP
> **Full Reference**: See [patterns.md](patterns.md) for Performance Monitoring, Retry Logic, Audit Logging, Security Check, Rate Limiting, and Testing patterns.
## Quick Start
```java
@SpringBootApplication
@EnableAspectJAutoProxy
public class Application {}
@Aspect
@Component
@Slf4j
public class LoggingAspect {
@Around("execution(* com.example.service.*.*(..))")
public Object logExecution(ProceedingJoinPoint joinPoint) throws Throwable {
String method = joinPoint.getSignature().toShortString();
log.info("Executing: {}", method);
long start = System.currentTimeMillis();
Object result = joinPoint.proceed();
long duration = System.currentTimeMillis() - start;
log.info("Completed: {} in {} ms", method, duration);
return result;
}
}
```
---
## Pointcut Expressions
### Method Execution
```java
@Aspect
@Component
public class PointcutExamples {
// All methods in a package
@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceLayer() {}
// Public methods
@Pointcut("execution(public * *(..))")
public void publicMethods() {}
// Methods starting with "get"
@Pointcut("execution(* get*(..))")
public void getters() {}
// Package and subpackages
@Pointcut("execution(* com.example..*.*(..))")
public void entireApplication() {}
}
```
### Annotation-Based
```java
@Aspect
@Component
public class AnnotationPointcuts {
// Methods annotated with @Transactional
@Pointcut("@annotation(org.springframework.transaction.annotation.Transactional)")
public void transactionalMethods() {}
// Classes annotated with @Service
@Pointcut("@within(org.springframework.stereotype.Service)")
public void serviceBeans() {}
// With annotation binding
@Around("@annotation(loggable)")
public Object logWithAnnotation(ProceedingJoinPoint pjp, Loggable loggable) throws Throwable {
String value = loggable.value();
return pjp.proceed();
}
}
```
### Combinations
```java
@Aspect
@Component
public class CombinedPointcuts {
@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceLayer() {}
@Pointcut("execution(* com.example.repository.*.*(..))")
public void repositoryLayer() {}
// AND
@Pointcut("serviceLayer() && publicMethods()")
public void publicServiceMethods() {}
// OR
@Pointcut("serviceLayer() || repositoryLayer()")
public void dataLayer() {}
// NOT
@Pointcut("serviceLayer() && !execution(* get*(..))")
public void nonGetterServiceMethods() {}
}
```
---
## Advice Types
### @Around
```java
@Aspect
@Component
public class AroundAdvice {
@Around("execution(* com.example.service.*.*(..))")
public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
log.info("Before: {} with args: {}", methodName, Arrays.toString(args));
try {
Object result = joinPoint.proceed();
log.info("After returning: {} returned: {}", methodName, result);
return result;
} catch (Exception e) {
log.error("After throwing: {} threw: {}", methodName, e.getMessage());
throw e;
}
}
// Modify arguments
@Around("execution(* com.example.service.UserService.createUser(..))")
public Object sanitizeInput(ProceedingJoinPoint joinPoint) throws Throwable {
Object[] args = joinPoint.getArgs();
for (int i = 0; i < args.length; i++) {
if (args[i] instanceof String str) {
args[i] = sanitize(str);
}
}
return joinPoint.proceed(args);
}
}
```
### @Before, @After, @AfterReturning, @AfterThrowing
```java
@Aspect
@Component
public class OtherAdvice {
@Before("execution(* com.example.service.*.*(..))")
public void logBefore(JoinPoint joinPoint) {
log.info("Entering: {}", joinPoint.getSignature().toShortString());
}
@After("execution(* com.example.service.*.*(..))")
public void logAfter(JoinPoint joinPoint) {
log.info("Completed: {}", joinPoint.getSignature().toShortString());
}
@AfterReturning(pointcut = "execution(* com.example.service.UserService.createUser(..))", returning = "user")
public void logCreatedUser(JoinPoint joinPoint, User user) {
log.info("Created user: {}", user.getId());
}
@AfterThrowing(pointcut = "execution(* com.example.service.*.*(..))", throwing = "ex")
public void logException(JoinPoint joinPoint, Exception ex) {
log.error("Exception in {}: {}", joinPoint.getSignature().toShortString(), ex.getMessage());
}
}
```
---
## Custom Annotations
```java
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Loggable {
String value() default "";
boolean logArgs() default true;
boolean logResult() default true;
LogLevel level() default LogLevel.INFO;
}
@Aspect
@Component
@Slf4j
public class LoggableAspect {
@Around("@annotation(loggable)")
public Object logMethod(ProceedingJoinPoint joinPoint, Loggable loggable) throws Throwable {
String methodName = joinPoint.getSignature().toShortString();
String message = loggable.value().isEmpty() ? methodName : loggable.value();
if (loggable.logArgs()) {
log.info("Entering {} with args: {}", message, Arrays.toString(joinPoint.getArgs()));
}
long start = System.currentTimeMillis();
Object result = joinPoint.proceed();
if (loggable.logResult()) {
log.info("Exiting {} with result: {} ({}ms)", message, result, System.currentTimeMillis() - start);
}
return result;
}
}
// Usage
@Service
public class UserService {
@Loggable(value = "Creating user", logResult = false)
public User createUser(CreateUserRequest request) {
return userRepository.save(new User(request));
}
}
```
---
## Aspect Ordering
```java
@Aspect
@Component
@Order(1) // Executes first
public class SecurityAspect { }
@Aspect
@Component
@Order(2) // Executes second
public class LoggingAspect { }
@Aspect
@Component
@Order(3) // Executes third
public class PerformanceAspect { }
```
---
## Best Practices
- Use specific pointcuts (not too broad)
- Order aspects with @Order
- Use custom annotations for clarity
- Avoid complex logic in aspects
- Monitor performance impact
- Test aspects in isolation
- Don't catch exceptions silently
- Don't modify shared state
- Don't use for core business logic
## Common Pitfalls
| Error | Cause | Solution |
|-------|-------|----------|
| Aspect not applied | Bean not Spring-managed | Use @Component or @Bean |
| Self-invocation | Internal call bypasses proxy | Use self-injection |
| Wrong order | Aspects not ordered | Use @Order |
| Performance | Aspect too broad | Narrow pointcut |
## Quick Troubleshooting
| Issue | Possible Cause | Solution |
|-------|---------------|----------|
| Aspect not executing | Bean not Spring-managed | Ensure class has @Component |
| Self-invocation doesn't trigger | Internal call bypasses proxy | Use self-injection |
| Wrong execution order | Missing @Order | Add @Order with priority |
| Performance degradation | Pointcut too broad | Narrow scope, use custom annotations |
## Reference Documentation
- [Spring AOP](https://docs.spring.io/spring-framework/reference/core/aop.html)
- [AspectJ Pointcut Expressions](https://www.eclipse.org/aspectj/doc/released/progguide/semantics-pointcuts.html)
Related in Security
mac-ops
IncludedComprehensive macOS workstation operations — diagnose kernel panics, identify failing drives, audit launchd startup items, decode wake reasons, triage TCC permission denials, manage APFS snapshots, recover from no-boot. Use for: Mac is slow, slow bootup, won't boot, kernel panic, kernel_task hot, mds_stores CPU, photoanalysisd, cloudd, login loop, gray screen, sleep wake failure, drive failing, IO errors, APFS snapshots eating space, Time Machine local snapshots, Spotlight indexing, launchd, LaunchAgent, LaunchDaemon, login items, TCC permissions, Full Disk Access, Screen Recording denied, Gatekeeper, quarantine, com.apple.quarantine, app is damaged, helper tool, /Library/PrivilegedHelperTools, pmset, wake reasons, dark wake, sysdiagnose, panic.ips, DiagnosticReports, configuration profile, MDM profile, remote diagnostics over SSH.
a11y-audit
IncludedRun accessibility audits on web projects combining automated scanning (axe-core, Lighthouse) with WCAG 2.1 AA compliance mapping, manual check guidance, and structured reporting. Output is configurable: markdown report only, markdown plus machine-readable JSON, or markdown plus issue tracker integration. Use this skill whenever the user mentions "accessibility audit", "a11y audit", "WCAG audit", "accessibility check", "compliance scan", or asks to check a web project for accessibility issues. Also trigger when the user wants to verify WCAG conformance or map findings to a specific standard (CAN-ASC-6.2, EN 301 549, ADA/AODA).
erpclaw
IncludedAI-native ERP system with self-extending OS. Full accounting, invoicing, inventory, purchasing, tax, billing, HR, payroll, advanced accounting (ASC 606/842, intercompany, consolidation), and financial reporting. 413 actions across 14 domains, 43 expansion modules. Constitutional guardrails, adversarial audit, schema migration. Double-entry GL, immutable audit trail, US GAAP.
assess
IncludedAssesses and rates quality 0-10 across multiple dimensions (correctness, maintainability, security, performance, testability, simplicity) with pros/cons analysis. Compares against project conventions and prior decisions from memory. Produces structured evaluation reports with actionable improvement suggestions. Use when evaluating code, designs, architectures, or comparing alternative approaches.
spring-boot-security-jwt
IncludedProvides JWT authentication and authorization patterns for Spring Boot 3.5.x covering token generation with JJWT, Bearer/cookie authentication, database/OAuth2 integration, and RBAC/permission-based access control using Spring Security 6.x. Use when implementing authentication or authorization in Spring Boot applications.
code-hardcode-audit
IncludedDetect hardcoded values, magic numbers, and leaked secrets. TRIGGERS - hardcode audit, magic numbers, PLR2004, secret scanning.