Spring AOP(八)AOP多切面编程

转载自 https://blog.csdn.net/Sadlay/article/details/83510991

AOP多切面编程

Spring可以支持多个切面的运行。

首先我们来创建3个切面类。

MyAspect1

package com.lay.springboot_aop.aspect;

@Aspect
public class MyAspect1 {

@Pointcut("execution(* com.lay.springboot_aop.aspect.service.impl.UserServiceImpl.printUser(..))")
public void pointCut() {
}

@Before("pointCut()")
public void before(JoinPoint point ,User user) {
    System.out.println("MyAspect1 before-----------");
}

@After("pointCut()")
public void after() {
    System.out.println("MyAspect1 after------------");
}

@AfterReturning("pointCut()")
public void afterReturning() {
    System.out.println("MyAspect1 afterReturning------------");
}

@AfterThrowing("pointCut()")
public void afterThrowning() {
    System.out.println("MyAspect1 afterThrowning------------");
}

}

MyAspect2

package com.lay.springboot_aop.aspect;

@Aspect
public class MyAspect2 {

@Pointcut("execution(* com.lay.springboot_aop.aspect.service.impl.UserServiceImpl.printUser(..))")
public void pointCut() {
}

@Before("pointCut()")
public void before(JoinPoint point ,User user) {
    System.out.println("MyAspect2 before-----------");
}

@After("pointCut()")
public void after() {
    System.out.println("MyAspect2 after------------");
}

@AfterReturning("pointCut()")
public void afterReturning() {
    System.out.println("MyAspect2 afterReturning------------");
}

@AfterThrowing("pointCut()")
public void afterThrowning() {
    System.out.println("MyAspect2 afterThrowning------------");
}

}

MyAspect3

package com.lay.springboot_aop.aspect;

@Aspect
public class MyAspect3 {

@Pointcut("execution(* com.lay.springboot_aop.aspect.service.impl.UserServiceImpl.printUser(..))")
public void pointCut() {
}

@Before("pointCut()")
public void before(JoinPoint point ,User user) {
    System.out.println("MyAspect3 before-----------");
}

@After("pointCut()")
public void after() {
    System.out.println("MyAspect3 after------------");
}

@AfterReturning("pointCut()")
public void afterReturning() {
    System.out.println("MyAspect3 afterReturning------------");
}

@AfterThrowing("pointCut()")
public void afterThrowning() {
    System.out.println("MyAspect3 afterThrowning------------");
}

}

这样我们就定义了三个切面,它们同时拦截UserServiceImplmanyAspects()方法

UserServiceImpl

public class UserServiceImpl implements UserService{
    @override
    public void manyAspects(){
        system.out.println("测试多个切面顺序");
    }
}

接着在UserController控制器中加入新的方法,已方便我们测试。

UserController

@Controller
@RequestMapping("/user")
public class UserController{
// 注入用户服务service
@Autowired
private UserService userService;

@RequestMapping("/manyAspects")
public String manyAspects(){
    userService.manyAspects();
    return "manyAspects";
}

}

这样我们通过浏览器地址栏输入URL就会调用了UserServiceImpl的manyAspects方法,然后再配置文件中加入3个切面的Bean。

SpringbootAopApplication启动主函数

package com.lay.springboot_aop;

//@SpringBootApplication(scanBasePackages= {“com.lay.springboot_aop.aspect”})
@SpringBootApplication
public class SpringbootAopApplication {

public static void main(String[] args) {
	SpringApplication.run(SpringbootAopApplication.class, args);
}

// 切面1
@Bean(name="myAspect1")
public MyAspect initMyAspect() {
    return new MyAspect1();
}

// 切面2
@Bean(name="myAspect2")
public MyAspect initMyAspect() {
    return new MyAspect2();
}	

// 切面3
@Bean(name="myAspect3")
public MyAspect initMyAspect() {
    return new MyAspect3();
}

}

运行测试,日志如下

myAspect2 before-------
myAspect1 before-------
myAspect3 before-------
测试多个切面
myAspect3 after--------
myAspect3 afterReturning--------
myAspect1 after--------
myAspect1 afterReturning--------
myAspect2 after--------
myAspect2 afterReturning--------

从日志中可以看出,切面的执行顺序是乱的。

我们需要确定切面的执行顺序,来决定哪些切面先执行,哪些切面后执行。为此,Spring提供了注解@Order来一个接口Ordered,它们都可以来指定切面的顺序。

@Order注解

我们使用@Order注解制定MyAspect1顺序为1

package com.lay.springboot_aop.aspect;

@Aspect
@Order(1)
public class MyAspect1 {
//…
}

同样的,我们也可以指定MyAspect2的顺序为2,MyAspect3的顺序为3,再次进行测试

打印日志

myAspect1 before-------
myAspect2 before-------
myAspect3 before-------
测试多个切面
myAspect3 after--------
myAspect3 afterReturning--------
myAspect2 after--------
myAspect2 afterReturning--------
myAspect1 after--------
myAspect1 afterReturning--------

我们可以看到对于前置通知(before)都是从小到大运行的,而对于后置通知和返回通知都是从大到小运行的,这就是典型的责任链模式的顺序。

Ordered接口

同样地,使用Ordered接口也可以指定顺序。

package com.lay.springboot_aop.aspect;

@Aspect
public class MyAspect1 implements Ordered{

//指定顺序
@Override
public int getOrder(){
    return 1;
}
//.......

}

你可能感兴趣的:(Spring,AOP,后台)