Spring Boot starter for aspect-oriented programming with Spring AOP and AspectJ
npx @tessl/cli install tessl/maven-org-springframework-boot--spring-boot-starter-aop@3.5.0Spring Boot starter for aspect-oriented programming with Spring AOP and AspectJ. This starter automatically configures Spring AOP support and enables developers to implement cross-cutting concerns like logging, security, transactions, and caching through declarative programming using annotations and pointcut expressions.
Package Name: spring-boot-starter-aop
Group ID: org.springframework.boot
Language: Java
Installation:
implementation 'org.springframework.boot:spring-boot-starter-aop:3.5.3'For Maven:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>3.5.3</version>
</dependency>import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.stereotype.Component;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.AfterReturning;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.service.*.*(..))")
public void logBefore(JoinPoint joinPoint) {
System.out.println("Executing: " + joinPoint.getSignature().getName());
}
@AfterReturning(pointcut = "execution(* com.example.service.*.*(..))", returning = "result")
public void logAfterReturning(JoinPoint joinPoint, Object result) {
System.out.println("Completed: " + joinPoint.getSignature().getName() +
" with result: " + result);
}
}The starter provides these configuration properties for customizing AOP behavior:
# Enable/disable AOP auto-configuration
# Type: Boolean
# Default: true (when missing, defaults to true)
# Description: Add @EnableAspectJAutoProxy support
spring.aop.auto=true
# Control proxy type for AOP proxies
# Type: Boolean
# Default: true (when missing, defaults to true)
# Description: Whether subclass-based (CGLIB) proxies are to be created (true),
# as opposed to standard Java interface-based proxies (false)
spring.aop.proxy-target-class=trueThe starter enables AOP through several key components:
AopAutoConfiguration automatically enables @EnableAspectJAutoProxy when conditions are metCreate aspects by combining @Aspect with @Component annotations.
@Aspect
@Component
public class AspectName {
// Aspect methods with advice annotations
}Define join points where advice should be executed.
@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceLayerPointcut() {}
@Pointcut("@annotation(org.springframework.transaction.annotation.Transactional)")
public void transactionalMethods() {}
@Pointcut("within(com.example.controller..*)")
public void controllerPackage() {}Common Pointcut Expressions:
execution(* package.Class.method(..)) - Method executionwithin(package..*) - Within package or subpackages@annotation(AnnotationType) - Methods with specific annotationargs(ArgType) - Methods with specific argument typestarget(TargetType) - Methods on specific target typesExecute advice before method execution.
/**
* Executes before the target method
* @param joinPoint - Provides access to method signature and arguments
*/
@Before("pointcut-expression")
public void beforeAdvice(JoinPoint joinPoint) {
// Advice logic
}Execute advice after successful method completion.
/**
* Executes after method returns successfully
* @param joinPoint - Provides access to method signature and arguments
* @param result - The return value (optional parameter)
*/
@AfterReturning(pointcut = "pointcut-expression", returning = "result")
public void afterReturningAdvice(JoinPoint joinPoint, Object result) {
// Advice logic
}Execute advice after method throws an exception.
/**
* Executes after method throws an exception
* @param joinPoint - Provides access to method signature and arguments
* @param exception - The thrown exception (optional parameter)
*/
@AfterThrowing(pointcut = "pointcut-expression", throwing = "exception")
public void afterThrowingAdvice(JoinPoint joinPoint, Exception exception) {
// Exception handling logic
}Execute advice after method completion (success or exception).
/**
* Executes after method completion regardless of outcome
* @param joinPoint - Provides access to method signature and arguments
*/
@After("pointcut-expression")
public void afterAdvice(JoinPoint joinPoint) {
// Cleanup logic
}Execute advice around method execution with control over method invocation.
/**
* Executes around method execution with full control
* @param proceedingJoinPoint - Allows proceeding with method execution
* @return Object - Must return the method result or alternative value
* @throws Throwable - Can throw exceptions
*/
@Around("pointcut-expression")
public Object aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
// Before logic
Object result = proceedingJoinPoint.proceed(); // Execute target method
// After logic
return result;
}Provides access to join point information in advice methods.
interface JoinPoint {
/** Get method signature information */
Signature getSignature();
/** Get method arguments */
Object[] getArgs();
/** Get target object instance */
Object getTarget();
/** Get proxy object instance */
Object getThis();
/** Get join point kind (METHOD_EXECUTION, etc.) */
String getKind();
/** Get source location information */
SourceLocation getSourceLocation();
}Extended join point interface for around advice with execution control.
interface ProceedingJoinPoint extends JoinPoint {
/** Proceed with original method execution */
Object proceed() throws Throwable;
/** Proceed with modified arguments */
Object proceed(Object[] args) throws Throwable;
}Provides method signature information.
interface Signature {
/** Get method name */
String getName();
/** Get declaring type */
Class<?> getDeclaringType();
/** Get method modifiers */
int getModifiers();
/** Get string representation */
String toString();
}/**
* Auto-configuration for Spring AOP support
* Equivalent to enabling @EnableAspectJAutoProxy
* Conditionally activated based on spring.aop.auto property
*/
@AutoConfiguration
@ConditionalOnBooleanProperty(name = "spring.aop.auto", matchIfMissing = true)
public class AopAutoConfiguration {
// Configuration classes for different proxy strategies
}Configuration Classes:
org.aspectj.weaver.Advice is on classpathspring.aop.proxy-target-class=falsespring.aop.proxy-target-class=true (default)@Aspect
@Component
public class ServiceMonitor {
private static final Logger logger = LoggerFactory.getLogger(ServiceMonitor.class);
@Around("execution(* com.example.service.*.*(..))")
public Object monitorServiceCall(ProceedingJoinPoint joinPoint) throws Throwable {
String methodName = joinPoint.getSignature().getName();
long startTime = System.currentTimeMillis();
try {
logger.info("Starting method: {}", methodName);
Object result = joinPoint.proceed();
long duration = System.currentTimeMillis() - startTime;
logger.info("Completed method: {} in {}ms", methodName, duration);
return result;
} catch (Exception e) {
logger.error("Method {} failed: {}", methodName, e.getMessage());
throw e;
}
}
}@Aspect
@Component
public class SecurityAspect {
@Before("@annotation(secured)")
public void checkSecurity(JoinPoint joinPoint, Secured secured) {
// Get current user context
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth == null || !auth.isAuthenticated()) {
throw new SecurityException("User not authenticated");
}
// Check required roles
String[] requiredRoles = secured.value();
boolean hasRole = Arrays.stream(requiredRoles)
.anyMatch(role -> auth.getAuthorities().stream()
.anyMatch(authority -> authority.getAuthority().equals(role)));
if (!hasRole) {
throw new SecurityException("Insufficient permissions");
}
}
}@Aspect
@Component
public class TransactionAspect {
@AfterThrowing(pointcut = "@annotation(transactional)", throwing = "exception")
public void handleTransactionException(JoinPoint joinPoint,
Transactional transactional,
Exception exception) {
// Custom transaction rollback logic
String methodName = joinPoint.getSignature().getName();
logger.error("Transaction rolled back for method: {} due to: {}",
methodName, exception.getMessage());
}
}@EnableAspectJAutoProxy annotation required@Component or equivalent)