约定编程Spring AOP-多个切面

上面我们讨论了一个切面的运行,而事实上Spring还可以支持多个切面的运行。在组织多个切面的时候,我们需要知道其运行的顺序,首先我们创建3个切面类,如下代码所示

package cn.hctech2006.boot.bootaop.aspect;

import org.aspectj.lang.annotation.*;

@Aspect
public class MyAspect1 {
    @Pointcut("execution(* cn.hctech2006.boot.bootaop.service.impl.UserServiceImpl.manyAspects())")
    public void pointCut(){

    }
    @Before("pointCut()")
    public void before(){
        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......");
    }
}

package cn.hctech2006.boot.bootaop.aspect;

import org.aspectj.lang.annotation.*;

@Aspect
public class MyAspect2 {
    @Pointcut("execution(* cn.hctech2006.boot.bootaop.service.impl.UserServiceImpl.manyAspects())")
    public void pointCut(){

    }
    @Before("pointCut()")
    public void before(){
        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......");
    }
}

package cn.hctech2006.boot.bootaop.aspect;

import org.aspectj.lang.annotation.*;

@Aspect
public class MyAspect3 {
    @Pointcut("execution(* cn.hctech2006.boot.bootaop.service.impl.UserServiceImpl.manyAspects())")
    public void pointCut(){

    }
    @Before("pointCut()")
    public void before(){
        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......");
    }
}

这样就存在了三个切面,他们同时拦截USerServiceImpl的manyAspect方法,所以我们现在就来实现这个新的方法,代码如下:

    @Override
    public void manyAspects() {
        System.out.println("测试多个切面的顺序");
    }

同期,需要改造UserService接口提供manyAspects方法。这个过程比较简单,这里就不演示这个过程。接着在UserController这个控制器加入新的方法,对于多个切面进行测试,如代码清单所示:

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

这样我们就带调用了UserServcieImpl的manyAspect方法,然后配置文件加入这三个切面的Bean

package cn.hctech2006.boot.bootaop;

@SpringBootApplication(scanBasePackages = {"cn.hctech2006.boot.bootaop.*"})
public class BootAopApplication {

    //定义切面
    @Bean(name = "myAspect")
    public MyAspect initMyAspect(){
        return new MyAspect();
    }
    //定义切面
    @Bean(name = "myAspect1")
    public MyAspect1 initMyAspect1(){
        return new MyAspect1();
    }
    //定义切面
    @Bean(name = "myAspect2")
    public MyAspect2 initMyAspect2(){
        return new MyAspect2();
    }
    //定义切面
    @Bean(name = "myAspect3")
    public MyAspect3 initMyAspect3(){
        return new MyAspect3();
    }
    //启动切面
    public static void main(String[] args) {
        SpringApplication.run(BootAopApplication.class, args);
    }

}

运行这三个文件就可以看到Tomcat运行的日志,待到启动好了之后,在浏览器输入http://localhost:8241/user/manyAspects,,可以在日志看到

MyAspect1 before....
MyAspect2 before....
MyAspect3 before....
测试多个切面的顺序
MyAspect3 after......
MyAspect3 afterReturning......
MyAspect2 after......
MyAspect2 afterReturning......
MyAspect1 after......
MyAspect1 afterReturning......

很多时候开发者需要确定切面的执行顺序,来决定那些切面先执行,那些切面后执行。为此,Spring提供了一个注解@Order和一个接口Ordered,我们可以使用他们的任意一个指定切面的顺序,下面我们先展示@Order,例如,我们指定MyAspect3的顺序是1,代码如下:

@Aspect
@Order(1)
public class MyAspect3 {}

同样的我们也可以指定MyAspect2的顺序是2,MyAspect1的顺序是3,这样我们再次测试就可以得到下面的日志:

MyAspect3 before....
MyAspect2 before....
MyAspect1 before....
测试多个切面的顺序
MyAspect1 after......
MyAspect1 afterReturning......
MyAspect2 after......
MyAspect2 afterReturning......
MyAspect3 after......
MyAspect3 afterReturning......

我们可以看到,对于前置通知(Before)都是按照@Order顺序从小到大运行的,而对于后置通知和返回通知都是按照Order顺序从大到小运行,这就是一个典型的责任链模式的顺序。同样的,使用Orderd接口也可以指定顺序。代码如下:

package cn.hctech2006.boot.bootaop.aspect;

import org.aspectj.lang.annotation.*;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;

@Aspect
//@Order(1)
public class MyAspect3 implements Ordered {
    @Override
    public int getOrder() {
        return 1;
    }
    @Pointcut("execution(* cn.hctech2006.boot.bootaop.service.impl.UserServiceImpl.manyAspects())")
    public void pointCut(){

    }
    @Before("pointCut()")
    public void before(){
        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......");
    }


}

其他的同样类似,不再赘言,同时推荐使用@Order注解。

发布了180 篇原创文章 · 获赞 114 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_43404791/article/details/105462637