Introduction to Advice Types in Spring – Spring中的建议类型介绍

最后修改: 2015年 12月 17日

1. Overview


In this article, we’ll discuss different types of AOP advice that can be created in Spring.


Advice is an action taken by an aspect at a particular join point. Different types of advice include “around,” “before” and “after” advice. The main purpose of aspects is to support cross-cutting concerns, such as logging, profiling, caching, and transaction management.

建议是一个方面在特定连接点采取的行动。不同类型的建议包括 “周围”、”之前 “和 “之后 “的建议。方面的主要目的是支持跨领域的关注,如日志、分析、缓存和事务管理。

And if you want to go deeper into pointcut expressions, check out the previous intro to these.


2. Enabling Advice


With Spring, you can declare advice using AspectJ annotations, but you must first apply the @EnableAspectJAutoProxy annotation to your configuration class, which will enable support for handling components marked with AspectJ’s @Aspect annotation.


public class AopConfiguration {

2.1. Spring Boot


In Spring Boot projects, we don’t have to explicitly use the @EnableAspectJAutoProxy. There’s a dedicated AopAutoConfiguration that enables Spring’s AOP support if the Aspect or Advice is on the classpath.

在Spring Boot项目中,我们不需要明确使用@EnableAspectJAutoProxy。有一个专门的AopAutoConfiguration,如果AspectAdvice在classpath上,就可以启用Spring的AOP支持。

3. Before Advice


This advice, as the name implies, is executed before the join point. It doesn’t prevent the continued execution of the method it advises unless an exception is thrown.


Consider the following aspect that simply logs the method name before it is called:


public class LoggingAspect {

    private Logger logger = Logger.getLogger(LoggingAspect.class.getName());

    public void repositoryMethods() {};

    public void logMethodCall(JoinPoint jp) {
        String methodName = jp.getSignature().getName();"Before " + methodName);

The logMethodCall advice will be executed before any repository method defined by the repositoryMethods pointcut.


4. After Advice


After advice, declared by using the @After annotation, is executed after a matched method’s execution, whether or not an exception was thrown.

After建议,通过使用@After 注解来声明,在匹配的方法执行后执行,无论是否抛出了异常。

In some ways, it is similar to a finally block. In case you need advice to be triggered only after normal execution, you should use the returning advice declared by @AfterReturning annotation. If you want your advice to be triggered only when the target method throws an exception, you should use throwing advice, declared by using the @AfterThrowing annotation.


Suppose that we wish to notify some application components when a new instance of Foo is created. We could publish an event from FooDao, but this would violate the single responsibility principle.


Instead, we can accomplish this by defining the following aspect:


public class PublishingAspect {

    private ApplicationEventPublisher eventPublisher;

    public void setEventPublisher(ApplicationEventPublisher eventPublisher) {
        this.eventPublisher = eventPublisher;

    public void repositoryMethods() {}

    @Pointcut("execution(* *..create*(Long,..))")
    public void firstLongParamMethods() {}

    @Pointcut("repositoryMethods() && firstLongParamMethods()")
    public void entityCreationMethods() {}

    @AfterReturning(value = "entityCreationMethods()", returning = "entity")
    public void logMethodCall(JoinPoint jp, Object entity) throws Throwable {
        eventPublisher.publishEvent(new FooCreationEvent(entity));

Notice, first, that by using the @AfterReturning annotation we can access the target method’s return value. Second, by declaring a parameter of type JoinPoint, we can access the arguments of the target method’s invocation.


Next we create a listener which will simply log the event:


public class FooCreationEventListener implements ApplicationListener<FooCreationEvent> {

    private Logger logger = Logger.getLogger(getClass().getName());

    public void onApplicationEvent(FooCreationEvent event) {"Created foo instance: " + event.getSource().toString());

5. Around Advice


Around advice surrounds a join point such as a method invocation.


This is the most powerful kind of advice. Around advice can perform custom behavior both before and after the method invocation. It’s also responsible for choosing whether to proceed to the join point or to shortcut the advised method execution by providing its own return value or throwing an exception.


To demonstrate its use, suppose that we want to measure method execution time. Let’s create an Aspect for this:


public class PerformanceAspect {

    private Logger logger = Logger.getLogger(getClass().getName());

    @Pointcut("within(@org.springframework.stereotype.Repository *)")
    public void repositoryClassMethods() {};

    public Object measureMethodExecutionTime(ProceedingJoinPoint pjp) throws Throwable {
        long start = System.nanoTime();
        Object retval = pjp.proceed();
        long end = System.nanoTime();
        String methodName = pjp.getSignature().getName();"Execution of " + methodName + " took " + 
          TimeUnit.NANOSECONDS.toMillis(end - start) + " ms");
        return retval;

This advice is triggered when any of the join points matched by the repositoryClassMethods pointcut is executed.


This advice takes one parameter of type ProceedingJointPoint. The parameter gives us an opportunity to take action before the target method call. In this case, we simply save the method start time.


Second, the advice return type is Object since the target method can return a result of any type. If target method is void, null will be returned. After the target method call, we can measure the timing, log it, and return the method’s result value to the caller.


6. Overview


In this article, we’ve learned the different types of advice in Spring and their declarations and implementations. We defined aspects using schema-based approach and using AspectJ annotations. We have also provided several possible advice applications.


The implementation of all these examples and code snippets can be found in my GitHub project.