Implementing AOP with Spring and AspectJ

AspectJ is a powerful AOP (Aspect-Oriented Programming) framework that defines its own syntax for cross-cutting concerns and uses a bytecode weaver to generate standard Java class files. Spring integrates AspectJ’s capabilities to simplify AOP implementation.

AspectJ supports several types of advice:

  • Before advice: Executes before the target method.
  • After returning advice: Runs after a successful method return.
  • Around advice: Wraps the target method, allowing custom behavior before and after execution.
  • After throwing advice: Triggers when the target method throws a exception.
  • After (finally) advice: Always executes, regardless of outcome—similar to a finally block.

Pointcut Expressions

Pointcuts determine which methods are intercepted by aspects. The genarel syntax is:

execution(modifiers? returnType declaringType? methodName(paramList) throws?)

Key wildcards:

  • * matches zero or more characters in names or types.
  • .. in parameters means any number of arguments; in package names, it includes subpackages.
  • + after a type matches the class/interface and all subclasses/implementations.

Examples:

  • execution(public * *(..)) → any public method.
  • execution(* set*(..)) → any method starting with "set".
  • execution(* com.example.service..*.*(..)) → all methods in service and subpackages.
  • execution(* add(String, int))add method with specific parameter types.

XML-Based Configuration

  1. Target service:
public class StudentService implements IStudentService {
    public boolean addStudent(Student student) {
        System.out.println("Executing add operation");
        return true;
    }

    public boolean delStudent(Integer id) {
        int x = 1 / 0; // intentional exception
        System.out.println("Executing delete");
        return true;
    }

    // other methods...
}
  1. Aspect class:
public class LoggingAspect {
    public void logBefore() {
        System.out.println("[Before] Preparing to execute method");
    }

    public void logAfterReturning(Object result) {
        System.out.println("[AfterReturning] Result: " + result);
    }

    public void logAround(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("[Around] Before method");
        Object res = joinPoint.proceed();
        System.out.println("[Around] After method");
    }

    public void logOnException(Exception ex) {
        System.out.println("[AfterThrowing] Exception: " + ex.getMessage());
    }

    public void logFinally() {
        System.out.println("[After] Cleanup executed");
    }
}
  1. Spring XML configurasion (applicationContext.xml):
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id="studentService" class="com.example.service.impl.StudentService" />
    <bean id="loggingAspect" class="com.example.aspect.LoggingAspect" />

    <aop:config>
        <aop:pointcut id="addMethods" expression="execution(* add*(..))" />
        <aop:pointcut id="updateMethods" expression="execution(* update*(..))" />
        <aop:pointcut id="queryMethods" expression="execution(* get*(..))" />
        <aop:pointcut id="deleteMethods" expression="execution(* del*(..))" />

        <aop:aspect ref="loggingAspect">
            <aop:before method="logBefore" pointcut-ref="addMethods" />
            <aop:after-returning method="logAfterReturning(java.lang.Object)"
                                 pointcut-ref="updateMethods" returning="result" />
            <aop:around method="logAround" pointcut-ref="queryMethods" />
            <aop:after-throwing method="logOnException(java.lang.Exception)"
                                pointcut-ref="deleteMethods" throwing="ex" />
            <aop:after method="logFinally" pointcut-ref="deleteMethods" />
        </aop:aspect>
    </aop:config>
</beans>

Annotation-Based Configuration

Using annotations reduces XML but introduces code-level coupling.

  1. Annotated aspect:
@Aspect
public class AnnotationLoggingAspect {
    @Before("execution(* add*(..))")
    public void logBefore() {
        System.out.println("[Before] via annotation");
    }

    @AfterReturning(pointcut = "execution(* update*(..))", returning = "result")
    public void logAfterReturning(Object result) {
        System.out.println("[AfterReturning] Result: " + result);
    }

    @Around("execution(* get*(..))")
    public Object logAround(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("[Around] Start");
        Object output = pjp.proceed();
        System.out.println("[Around] End");
        return output;
    }

    @AfterThrowing(pointcut = "execution(* del*(..))", throwing = "ex")
    public void logOnException(Exception ex) {
        System.out.println("[AfterThrowing] Error: " + ex);
    }

    @After("execution(* del*(..))")
    public void logFinally() {
        System.out.println("[After] Final cleanup");
    }
}
  1. Minimal XML setup:
<beans ...>
    <bean id="studentService" class="com.example.service.impl.StudentService" />
    <bean id="annotationAspect" class="com.example.aspect.AnnotationLoggingAspect" />
    <aop:aspectj-autoproxy />
</beans>

Both approaches require the aspectjweaver library on the classpath. The annotation style is more concise but embeds AOP logic directly into Java classes, whereas XML keeps concerns externalized.

Tags: Spring aspectj aop java Spring MVC

Posted on Mon, 21 Sep 2026 16:27:41 +0000 by grantson