Clean • Professional
Spring AOP is mainly used to handle cross-cutting concerns—functionality that is required across multiple layers of an application but is not part of core business logic.
Logging is used to track method calls, input parameters, return values, and execution flow without adding logging code inside business methods.
System.out.println() or logger callsExample
@Before("execution(* com.example.service.*.*(..))")
publicvoidlogMethodCall() {
System.out.println("Method called");
}
Auditing records who performed an action, what action was performed, and when it happened.
Example
@AfterReturning("execution(* com.example.service.*.*(..))")
publicvoidauditAction() {
System.out.println("Audit entry saved");
}
Security checks verify user roles, permissions, or authentication status before executing a method.
Example
@Before("@annotation(AdminOnly)")
publicvoidcheckAdminAccess() {
System.out.println("Admin access verified");
}
Manages database transactions automatically—begin, commit, rollback.
Example
@Transactional
publicvoidprocessPayment() {
// business logic
}
Measures execution time of methods to detect slow operations.
Example
@Around("execution(* com.example.service.*.*(..))")
public ObjectmeasureTime(ProceedingJoinPoint pjp)throws Throwable {
longstart= System.currentTimeMillis();
Objectresult= pjp.proceed();
longend= System.currentTimeMillis();
System.out.println("Execution time: " + (end - start));
return result;
}
Centralized handling of exceptions thrown by methods.
Example
@AfterThrowing(
pointcut = "execution(* com.example.service.*.*(..))",
throwing = "ex"
)
publicvoidlogException(Exception ex) {
System.out.println("Exception occurred: " + ex.getMessage());
}
Stores method results to avoid repeated computation or database calls.
Example
@Cacheable("products")
public ProductgetProduct(Long id) {
return repository.findById(id);
}
Restricts how often a method or API can be called.
Example
@Around("execution(* com.example.controller.*.*(..))")
public ObjectrateLimit(ProceedingJoinPoint pjp)throws Throwable {
// check request count
return pjp.proceed();
}
Demonstrates real Spring architecture where:
Repository Layer
@Repository
publicclassPaymentRepository {
publicvoidsavePayment() {
System.out.println("Payment saved to DB");
}
}
Service Layer (Using DI)
@Service
publicclassPaymentService {
privatefinal PaymentRepository paymentRepository;
publicPaymentService(PaymentRepository paymentRepository) {
this.paymentRepository = paymentRepository;
}
publicvoidprocessPayment() {
paymentRepository.savePayment();
System.out.println("Processing payment");
}
}
Logging Aspect
@Aspect
@Component
publicclassLoggingAspect {
@Before("execution(* com.example.service.*.*(..))")
publicvoidbeforeLog() {
System.out.println("Service method started");
}
@After("execution(* com.example.service.*.*(..))")
publicvoidafterLog() {
System.out.println("Service method completed");
}
}
Client
↓
Spring Proxy
↓
@Before Advice
↓
ServiceMethod
↓
RepositoryCall
↓
@After Advice
↓
Response
👉 Spring AOP = Clean Code + Scalable Architecture + Enterprise Readiness