Spring AOP with Annotations: Pointcuts, Advice Types & Data Binding
This tutorial explains Spring AOP using annotations, covering core concepts like join points, pointcuts, and advice types (before, after, around, etc.), with detailed examples of pointcut expressions and how to access method parameters, return values, and exceptions in advice methods.
1.1 AOP Introduction and Purpose
AOP (Aspect Oriented Programming) is a programming paradigm that guides developers on organizing program structure. Unlike OOP (Object Oriented Programming), AOP enables functional enhancement without modifying the original method source code. Spring's philosophy is non-invasive (non-intrusive) development.
1.2 Core AOP Concepts
JoinPoint : A method currently being executed, e.g., update(), delete(), select().
Pointcut : The method(s) actually enhanced. For example, update() and delete() are pointcuts; select() is a join point but not a pointcut if not enhanced. A pointcut can describe a single method (e.g., com.itheima.dao.BookDao.save()) or match multiple methods (all save methods, all get* methods, all methods in interfaces ending with Dao, all methods with one parameter).
Advice : The operation executed before/after a pointcut, representing the enhanced common functionality. In Spring AOP, advice is implemented as a method.
Advice Class : The class containing advice methods.
Aspect : Describes the mapping between advice and pointcuts — which advice methods correspond to which pointcut methods.
2.2 AOP Getting Started Example
Maven Dependencies
<dependencies>
<!-- Spring core dependency, brings in spring-aop transitively -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<!-- AspectJ weaver for pointcut expression parsing -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
</dependencies>Advice Class with Pointcut and Before Advice
@Component
@Aspect
public class MyAdvice {
@Pointcut("execution(void com.itheima.dao.BookDao.update())")
private void pt(){}
@Before("pt()")
public void method(){
System.out.println(System.currentTimeMillis());
}
}Configuration Class Enabling AOP
@Configuration
@ComponentScan("package containing advice class")
@EnableAspectJAutoProxy
public class SpringConfig {}AOP Pointcut Expressions
Syntax Format
Standard format:
execution(access_modifier return_type package.Class.method(parameters) exception). Example: execution(public User com.service.UserService.findById(int)).
execution : action keyword indicating execution of the specified join point.
Access modifier (public, private, etc.) — optional.
Return type — required.
Package name — dot-separated for multi-level packages.
Class/interface name.
Method name.
Parameters — write parameter types directly, comma-separated.
Exception name — optional.
Wildcards
* : Matches a single arbitrary symbol; can appear independently or as prefix/suffix. Example: execution(public * com.*.UserService.find*(*)) matches any return type, any package under com, UserService class/interface, all methods starting with find, with one parameter of any type.
.. : Matches multiple consecutive arbitrary symbols; often used to simplify package and parameter lists. Example: execution(public User com..UserService.findById(..)) matches any sub-package under com, UserService, findById method with any parameters.
+ : Matches subclass types. Example: execution(* *..*Service+.*(..)) matches any method in any Service interface or its implementations.
AOP Advice Types
Before Advice (@Before)
Runs before the target method.
@Before("pt()")
public void before() {
System.out.println("before advice ...");
}After Advice (@After)
Runs after the target method completes (regardless of outcome).
@After("pt()")
public void after() {
System.out.println("after advice ...");
}After Returning Advice (@AfterReturning)
Runs after the target method returns normally.
@AfterReturning("pt()")
public void afterReturning() {
System.out.println("afterReturning advice ...");
}After Throwing Advice (@AfterThrowing)
Runs when the target method throws an exception.
@AfterThrowing("pt()")
public void afterThrowing() {
System.out.println("afterThrowing advice ...");
}Around Advice (@Around) — Key, Commonly Used
Wraps the target method, executing code before and after. Must accept ProceedingJoinPoint parameter and call proceed() to invoke the original method. Return type should be Object to propagate the original return value.
@Around("pt()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("around before advice ...");
Object ret = pjp.proceed();
System.out.println("around after advice ...");
return ret;
}Notes:
The parameter must be ProceedingJoinPoint; its proceed() invokes the original method and returns its result.
Return type should be Object to pass the original return value to the caller.
AOP Pointcut Data Retrieval
2.1 Getting Method Parameters
Available in @Before and @Around. JoinPoint describes the join point's runtime state; getArgs() returns the arguments array. ProceedingJoinPoint extends JoinPoint.
@Before("pt()")
public void before(JoinPoint jp) {
Object[] args = jp.getArgs();
System.out.println(Arrays.toString(args));
} @Around("pt()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
Object[] args = pjp.getArgs();
System.out.println(Arrays.toString(args));
Object ret = pjp.proceed();
return ret;
}2.2 Getting Return Value
Available in @AfterReturning and @Around. Use returning attribute to bind the return value to a parameter (name must match). In @Around, the return value of proceed() is the original method's return value.
@AfterReturning(value = "pt()", returning = "ret")
public void afterReturning(String ret) {
System.out.println("afterReturning advice ..." + ret);
} @Around("pt()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
Object ret = pjp.proceed();
return ret;
}2.3 Getting Exceptions
Available in @AfterThrowing and @Around. Use throwing attribute to bind the exception to a parameter. In @Around, wrap proceed() in try-catch to capture the exception.
@AfterThrowing(value = "pt()", throwing = "t")
public void afterThrowing(Throwable t) {
System.out.println("afterThrowing advice ..." + t);
} @Around("pt()")
public Object around(ProceedingJoinPoint pjp) {
Object ret = null;
try {
ret = pjp.proceed();
} catch (Throwable t) {
t.printStackTrace();
}
return ret;
}Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Captain
Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
