关于spring aop的具体使用,暂时不在这里讲解,后面会特定来讲解,本次主要探讨spring中通知执行的顺序。

spring中通知分为以下几种:

  1. before:前置通知,在方法执行之前执行
  2. around:环绕通知,在方法执行前后执行
  3. afterreturning:在方法执行成功后执行
  4. afterthrowning:异常通知,在方法发生异常后执行
  5. after:后置通知,在方法执行之后执行(不管方法执行成功还是失败)

下面我们将每种通知创建两个,代码如下:

1、before通知2个

package com.cn.aop.demo4;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 我的技术网站 2016/11/17 0017.
 */
@Component
@Aspect
@Order(100000)
public class Before1 {
    @Before(value = "execution(* com.cn.aop.demo4.*Impl.*(..))")
    public void exec(){
        Order order = this.getClass().getAnnotation(Order.class);
        System.out.println(Before1.class+" Before通知 order = "+order.value());
    }
}
package com.cn.aop.demo4;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 我的技术网站 2016/11/17 0017.
 */
@Component
@Aspect
@Order(100000)
public class Before2 {
    @Before(value = "execution(* com.cn.aop.demo4.*Impl.*(..))")
    public void exec(){
        Order order = this.getClass().getAnnotation(Order.class);
        System.out.println(Before2.class+" Before通知 order = "+order.value());
    }
}

2、around通知2个

package com.cn.aop.demo4;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 我的技术网站 2016/11/17 0017.
 */
@Component
@Aspect
@Order(100000)
public class Around1 {
    @Around(value = "execution(* com.cn.aop.demo4.*Impl.*(..))")
    public Object exec(ProceedingJoinPoint invocation) throws Throwable {
        Order order = this.getClass().getAnnotation(Order.class);
        System.out.println(Around1.class+" Around通知 order = "+order.value()+" start");
        Object result = invocation.proceed();
        System.out.println(Around1.class+" Around通知 order = "+order.value()+" end");
        return result;
    }
}
package com.cn.aop.demo4;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 我的技术网站 2016/11/17 0017.
 */
@Component
@Aspect
@Order(100000)
public class Around2 {
    @Around(value = "execution(* com.cn.aop.demo4.*Impl.*(..))")
    public Object exec(ProceedingJoinPoint invocation) throws Throwable {
        Order order = this.getClass().getAnnotation(Order.class);
        System.out.println(Around2.class+" Around通知 order = "+order.value()+" start");
        Object result = invocation.proceed();
        System.out.println(Around2.class+" Around通知 order = "+order.value()+" end");
        return result;
    }
}

3、afterreturning通知2个

package com.cn.aop.demo4;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 我的技术网站 2016/11/17 0017.
 */
@Component
@Aspect
@Order(100000)
public class AfterReturning1 {
    @AfterReturning(value = "execution(* com.cn.aop.demo4.*Impl.*(..))")
    public void exec(){
        Order order = this.getClass().getAnnotation(Order.class);
        System.out.println(AfterReturning1.class+" AfterReturning通知 order = "+order.value());
    }
}
package com.cn.aop.demo4;

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 我的技术网站 2016/11/17 0017.
 */
@Component
@Aspect
@Order(100000)
public class AfterReturning2 {
    @AfterReturning(value = "execution(* com.cn.aop.demo4.*Impl.*(..))")
    public void exec(){
        Order order = this.getClass().getAnnotation(Order.class);
        System.out.println(AfterReturning2.class+" AfterReturning通知 order = "+order.value());
    }
}

4、afterthrowning通知2个

package com.cn.aop.demo4;

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 我的技术网站 2016/11/17 0017.
 */
@Component
@Aspect
@Order(100000)
public class AfterThrowing1 {
    @AfterThrowing(value = "execution(* com.cn.aop.demo4.*Impl.*(..))")
    public void exec(){
        Order order = this.getClass().getAnnotation(Order.class);
        System.out.println(AfterThrowing1.class+" AfterThrowing通知 order = "+order.value());
    }
}
package com.cn.aop.demo4;

import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 我的技术网站 2016/11/17 0017.
 */
@Component
@Aspect
@Order(100000)
public class AfterThrowing2 {
    @AfterThrowing(value = "execution(* com.cn.aop.demo4.*Impl.*(..))")
    public void exec(){
        Order order = this.getClass().getAnnotation(Order.class);
        System.out.println(AfterThrowing2.class+" AfterThrowing通知 order = "+order.value());
    }
}

5、after通知两个

package com.cn.aop.demo4;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 我的技术网站 2016/11/17 0017.
 */
@Component
@Aspect
@Order
public class After1 {
    @After(value = "execution(* com.cn.aop.demo4.*Impl.*(..))")
    public void exec(){
        Order order = this.getClass().getAnnotation(Order.class);
        System.out.println(After1.class+" After通知 order = "+order.value());
    }
}
package com.cn.aop.demo4;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 我的技术网站 2016/11/17 0017.
 */
@Component
@Aspect
@Order(100000)
public class After2 {
    @After(value = "execution(* com.cn.aop.demo4.*Impl.*(..))")
    public void exec(){
        Order order = this.getClass().getAnnotation(Order.class);
        System.out.println(After2.class+" After通知 order = "+order.value());
    }
}

  • 声明1个接口和一个实现类,在本实现类上面添加上面10个通知

package com.cn.aop.demo4;

/**
 * 我的技术网站 2016/11/15 0015.
 */
public interface IAService {
    String m1();
    void m2();
}
package com.cn.aop.demo4;

import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * 我的技术网站 2016/11/15 0015.
 */
@Component("aservice")
public class AServiceImpl implements IAService {

    public String m1()
    {
        System.out.println(AServiceImpl.class+".m1()");
        return AServiceImpl.class+".m1()";
    }

    @Override
    public void m2() {
        int i=0;
        System.out.println(10/i);
    }
}
  • spring配置文件spring-demo4.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.1.xsd 
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop-3.1.xsd 
    http://www.springframework.org/schema/tx  
    http://www.springframework.org/schema/tx/spring-tx-3.1.xsd" default-autowire="byName">
    <aop:aspectj-autoproxy />
    <context:component-scan base-package="com.cn.aop.demo4"/>
</beans>

  • 测试类
package com.cn.aop.demo4;

import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 我的技术网站 2016/11/17 0017.
 */
public class Client {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:/aop/spring-demo4.xml");
        IAService aservice = context.getBean("aservice", IAService.class);
        System.out.println("\n========================\n");
        aservice.m1();
        System.out.println("\n========================\n");
        try {
            aservice.m2();
        } catch (Exception e){
            //暂时不输出错误信息
        }
    }
}

1、上面所有拦截器的order都为100000,执行结果如下

========================

class com.cn.aop.demo4.Around1 Around通知 order = 100000 start
class com.cn.aop.demo4.Around2 Around通知 order = 100000 start
class com.cn.aop.demo4.Before1 Before通知 order = 100000
class com.cn.aop.demo4.Before2 Before通知 order = 100000
class com.cn.aop.demo4.AServiceImpl.m1()
class com.cn.aop.demo4.Around2 Around通知 order = 100000 end
class com.cn.aop.demo4.Around1 Around通知 order = 100000 end
class com.cn.aop.demo4.AfterReturning1 AfterReturning通知 order = 100000
class com.cn.aop.demo4.AfterReturning2 AfterReturning通知 order = 100000
class com.cn.aop.demo4.After2 After通知 order = 100000
class com.cn.aop.demo4.After1 After通知 order = 100000

========================

class com.cn.aop.demo4.Around1 Around通知 order = 100000 start
class com.cn.aop.demo4.Around2 Around通知 order = 100000 start
class com.cn.aop.demo4.Before1 Before通知 order = 100000
class com.cn.aop.demo4.Before2 Before通知 order = 100000
class com.cn.aop.demo4.AfterThrowing2 AfterThrowing通知 order = 100000
class com.cn.aop.demo4.AfterThrowing1 AfterThrowing通知 order = 100000
class com.cn.aop.demo4.After2 After通知 order = 100000
class com.cn.aop.demo4.After1 After通知 order = 100000

Before1 @Order(1)
Before2 @Order(2)
Before1 @Order(1)
Before2 @Order(2)

client执行结果

========================

class com.cn.aop.demo4.Before1 Before通知 order = 1
class com.cn.aop.demo4.Before2 Before通知 order = 2
class com.cn.aop.demo4.Around1 Around通知 order = 100000 start
class com.cn.aop.demo4.Around2 Around通知 order = 100000 start
class com.cn.aop.demo4.AServiceImpl.m1()
class com.cn.aop.demo4.Around2 Around通知 order = 100000 end
class com.cn.aop.demo4.Around1 Around通知 order = 100000 end
class com.cn.aop.demo4.AfterReturning1 AfterReturning通知 order = 100000
class com.cn.aop.demo4.AfterReturning2 AfterReturning通知 order = 100000
class com.cn.aop.demo4.After2 After通知 order = 100000
class com.cn.aop.demo4.After1 After通知 order = 100000

========================

class com.cn.aop.demo4.Before1 Before通知 order = 1
class com.cn.aop.demo4.Before2 Before通知 order = 2
class com.cn.aop.demo4.Around1 Around通知 order = 100000 start
class com.cn.aop.demo4.Around2 Around通知 order = 100000 start
class com.cn.aop.demo4.AfterThrowing2 AfterThrowing通知 order = 100000
class com.cn.aop.demo4.AfterThrowing1 AfterThrowing通知 order = 100000
class com.cn.aop.demo4.After2 After通知 order = 100000
class com.cn.aop.demo4.After1 After通知 order = 100000

3、修改配置

Before1 @Order(1)
Before2 @Order(2)
AfterReturning1 @Order(1)
AfterReturning2 @Order(1000001)
AfterThrowing1 @Order(1)
AfterThrowing2 @Order(1000001)
After1 @Order(1)
After2 @Order(1000001)

========================

class com.cn.aop.demo4.Before1 Before通知 order = 1
class com.cn.aop.demo4.Before2 Before通知 order = 2
class com.cn.aop.demo4.Around1 Around通知 order = 100000 start
class com.cn.aop.demo4.Around2 Around通知 order = 100000 start
class com.cn.aop.demo4.AServiceImpl.m1()
class com.cn.aop.demo4.AfterReturning2 AfterReturning通知 order = 1000001
class com.cn.aop.demo4.After2 After通知 order = 1000001
class com.cn.aop.demo4.Around2 Around通知 order = 100000 end
class com.cn.aop.demo4.Around1 Around通知 order = 100000 end
class com.cn.aop.demo4.AfterReturning1 AfterReturning通知 order = 1
class com.cn.aop.demo4.After1 After通知 order = 1

========================

class com.cn.aop.demo4.Before1 Before通知 order = 1
class com.cn.aop.demo4.Before2 Before通知 order = 2
class com.cn.aop.demo4.Around1 Around通知 order = 100000 start
class com.cn.aop.demo4.Around2 Around通知 order = 100000 start
class com.cn.aop.demo4.AfterThrowing2 AfterThrowing通知 order = 1000001
class com.cn.aop.demo4.After2 After通知 order = 1000001
class com.cn.aop.demo4.AfterThrowing1 AfterThrowing通知 order = 1
class com.cn.aop.demo4.After1 After通知 order = 1

结论:

1、无异常情况

  • 所有通知order一样,执行顺序:around start -> before ->around start -> afterreturning -> after
  • before.order < around.order,执行顺序: before -> around start
  • afterreturning.order > around.order,执行顺序:afterreturning
  • after.order > around.order,执行顺序:after
  • after.order >afterreturning.order,执行顺序: after -> afterreturning

2、异常情况

  • 所有通知order一样,执行顺序:around start -> before ->  afterthrowing -> after
  • before.order < around.order,执行顺序: before -> around start
  • after.order > afterthrowing .order,执行顺序:after -> afterthrowing