SpringBoot应用AOP及各注解的执行顺序

首先第一步,POM引入jar

		
			org.springframework.boot
			spring-boot-starter-aop
		

		
			aspectj
			aspectjweaver
			1.5.3
		

第二步随便写一个类,然后类中写一个方法,我这里是写了一个除法运算:

public class MathCalculator {

    public int div (int i, int j) {
        System.out.println("MathCalculator.div...");
        return i / j;
    }
}

第三步写一个切面类:

//该注解表示声明该类为一个切面类
@Aspect
public class LogAspects {

    //定义一个切点,表达式可以灵活运用,我这个表达式是表示MathCalculator类中所有的方法都进行切入
    @Pointcut("execution(public int com.example.demo.aop.MathCalculator.*(..))")
    public void pointCut () {}

    //方法执行开始之前
    @Before("pointCut()")
    public void logStart (JoinPoint joinPoint) {
        System.out.println("除法运行...参数:{"+ Arrays.asList(joinPoint.getArgs())+"}");
    }

    //方法执行开始之后
    @After("pointCut()")
    public void logEnd (JoinPoint joinPoint) {
        System.out.println("除法结束..." + joinPoint.getSignature().getName());
    }

    //当方法进行返回的时候,returning属性是指定方法参数中的result来接收返回参数,这样就可以修改返回参数
    @AfterReturning(value = "pointCut()", returning = "result")
    public void logReturn (JoinPoint joinPoint, Object result) {
        System.out.println("除法正常返回... 返回结果:{"+result+"}");
    }

    //当方法执行异常的时候,throwding是指定方法参数中的e来接收异常参数,可以查看发生的什么异常
    @AfterThrowing(value = "pointCut()", throwing = "e")
    public void logException (JoinPoint joinPoint, Exception e) {
        System.out.println("异常... 异常信息:{"+e+"}");
    }

    //环绕通知
    @Around("pointCut()")
    public Object logAround (ProceedingJoinPoint joinPoint) throws Throwable {
        //原方法执行之前会打印这个日志
        System.out.println("环绕通知...  开始");
        //执行原方法
        Object obj = joinPoint.proceed();
        //原方法执行结束,打印这行日志
        System.out.println("环绕通知...  结束");
        //返回方法返回参数
        return obj;
    }
}

这里要注意一下AOP注解执行的先后顺序

环绕通知...  开始
除法运行...参数:{[1, 1]}
MathCalculator.div...
环绕通知...  结束
除法结束...div
除法正常返回... 返回结果:{1}

运行的顺序是

1、@Around

2、@Before

3、原方法

4、@Around

5、@After

6、@AfterReturning

第四步,写一个配置类,记得一定要加@EnableAspectJAutoProxy注解

//该配置类是为了将我们前2个类(切面类、被切面类)加入到Spring容器中
@Configuration
//启动AOP(一定要加这个注解,切记!!!)
@EnableAspectJAutoProxy
public class SpringOfAOPConfig {

    @Bean
    public MathCalculator mathCalculator () {
        return new MathCalculator();
    }

    @Bean
    public LogAspects logAspects () {
        return new LogAspects();
    }

}

第五步,测试:

@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {

	@Test
	public void contextLoads() {
	    //根据配置类获取SPring容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringOfAOPConfig.class);
        //从容器中获取Bean
        MathCalculator mathCalculator = applicationContext.getBean(MathCalculator.class);
        //执行除法运算
        mathCalculator.div(1, 1);
        //关闭容器
        applicationContext.close();
    }

}

 

 

正常结果:

2018-12-11 11:01:25.496  INFO 16364 --- [           main] com.example.demo.DemoApplicationTests    : Started DemoApplicationTests in 3.455 seconds (JVM running for 4.972)
环绕通知...  开始
除法运行...参数:{[1, 1]}
MathCalculator.div...
环绕通知...  结束
除法结束...div
除法正常返回... 返回结果:{1}
2018-12-11 11:01:25.807  INFO 16364 --- [       Thread-2] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'

异常结果:

2018-12-11 11:11:22.205  INFO 9628 --- [           main] com.example.demo.DemoApplicationTests    : Started DemoApplicationTests in 3.532 seconds (JVM running for 4.559)
环绕通知...  开始
除法运行...参数:{[1, 0]}
MathCalculator.div...
除法结束...div
异常... 异常信息:{java.lang.ArithmeticException: / by zero}

java.lang.ArithmeticException: / by zero

看到没:

发生异常的时候@Around的方法执行后切入没有进行,但是@After的方法却执行了,所以原方法发生异常后顺序就是

1、@Around

2、@Brfore

3、原方法

4、@After

5、@AfterThrowing

 

你可能感兴趣的:(JAVA,Spring)