zoukankan      html  css  js  c++  java
  • Spring切面通知执行的顺序(Advice Order)

    问题描述

    如果在Spring的程序中同时定义了环绕通知(Around)前置通知(Before)。.那么,有以下问题:
    1.怎么让两个切面通知都起作用
    2.或者让两者切面按自己指定的顺序进行执行?
    3.环绕通知和前置后置通知的区别

    引用知乎上的回答

    如果在同一接入点(join point) 有多个通知(advice),Spring AOP 采用和 AspectJ 类似的优先级来指定通知的执行顺序,目标执行前(进入时),优先级高的通知先执行,目标执行后(出来时),优先级高的通知后执行。

    如果两个通知分别定义在各自的 Aspect 内,可以通过如下两种方式控制 Aspect 的施加顺序:
    Aspect 类添加注解:org.springframework.core.annotation.Order
    顺序值:使用注解属性指定
    Aspect 类实现接口:org.springframework.core.Ordered
    顺序值:实现 Ordered 接口的 getOrder() 方法即可
    如果两个 advice 位于同一 aspect 内,且执行顺序有先后,通过 advice 的声明顺序是无法确定其执行顺序的,因为 advice 方法的声明顺序无法通过反射获取,只能采取如下变通方式,二选一:
    将两个 advice 合并为一个 advice,那么执行顺序就可以通过代码控制了
    将两个 advice 分别抽离到各自的 aspect 内,然后为 aspect 指定执行顺序
    作者:Night Silent
    链接:http://www.zhihu.com/question/32326290/answer/55572235
    来源:知乎
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    问题回答

    1. 怎么让两个切面通知都起作用

    将需要被执行的通知的实现类,在Sping中进行注册或者全部采用注解的方式和配置扫描包
    如果编写的环绕通知和前置后置通知没有问题,那么,通知就可以在切点出被调用。

    <bean id="aroundAudience"
          class="com.springinaction.springidol.AroundAudience">
    </bean>
    <bean id="audience" 
          class="com.springinaction.springidol.Audience" />

    2. 或者让两者切面按自己指定的顺序进行执行?

    你在Spring的配置文件中声明环绕通知和前置后置通知的顺序就是他们执行的先后顺序。由配置顺序决定执行先后顺序,本身没有优先级。

    3.环绕通知和前置后置通知的区别

    参考文档文档
    下面的地址是Spring官方给出的AOP切面的文档

    http://docs.spring.io/spring/docs/2.5.x/reference/aop.html#aop-ataspectj-advice-ordering
    使用Spring进行面向切面编程(AOP).
    http://www.blogjava.net/supercrsky/articles/174368.html
    跟我学SPring3.x之切面执行顺序
    http://jinnianshilongnian.iteye.com/blog/1423489


    下面用一个实例来说明如何执行多个通知,实例采用Maven进行依赖管理,通知采用注解形式的配置

    先上Spring的配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <!--<start id="preamble" />--> 
    <beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:aop="http://www.springframework.org/schema/aop"
     xsi:schemaLocation="http://www.springframework.org/schema/beans 
         http://www.springframework.org/schema/beans/spring-beans.xsd
         http://www.springframework.org/schema/aop
         http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--<end id="preamble" />-->
    
      <bean id="eddie"
          class="com.springinaction.springidol.Instrumentalist">
        <property name="instrument">
          <bean class="com.springinaction.springidol.Guitar" />
        </property>
      </bean>
    <bean id="aroundAudience"
          class="com.springinaction.springidol.AroundAudience">
    
    </bean>
      <!--<start id="audience_bean" />--> 
      <bean id="audience" 
          class="com.springinaction.springidol.Audience" />
      <!--<end id="audience_bean" />-->
    
      <!--<start id="contestant_introducer" />--> 
      <bean class="com.springinaction.springidol.ContestantIntroducer" />
      <!--<end id="contestant_introducer" />-->
    
      <!--<start id="aspectj_autoproxy" />--> 
        <aop:aspectj-autoproxy />
      <!--<end id="aspectj_autoproxy" />-->
    
    </beans>
    

    Instrument接口

    package com.springinaction.springidol;
    
    public interface Instrument {
      public void play();
    }
    

    Instrument实现类

    package com.springinaction.springidol;
    
    public class Guitar implements Instrument {
      public void play() {
        System.out.println("Strum strum strum");
      }
    }
    

    AroundAudience类(定义环绕通知的类)

    package com.springinaction.springidol;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    
    @Aspect
    public class AroundAudience {
    
      @Pointcut("execution(* com.springinaction.springidol.Performer.perform(..))")
      public void performance() {
    
      }
      //<start id="audience_around_bean" /> 
      @Around("performance()")
      public void watchPerformance(ProceedingJoinPoint joinpoint) {
        try {
          System.out.println("The audience is taking their seats.");
          System.out.println("The audience is turning off their cellphones");
    
          long start = System.currentTimeMillis();
          joinpoint.proceed();
          long end = System.currentTimeMillis();
    
          System.out.println("CLAP CLAP CLAP CLAP CLAP");
    
          System.out.println("The performance took " + (end - start)
              + " milliseconds.");
        } catch (Throwable t) {
          System.out.println("Boo! We want our money back!");
        }
      }
      //<end id="audience_around_bean" />
    }
    

    Audience定义前置通知

    package com.springinaction.springidol;
    
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.AfterThrowing;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    
    @Aspect
    public class Audience {
      @Pointcut(
            "execution(* com.springinaction.springidol.Performer.perform(..))")
      public void performance() { //<co id="co_definePointcut"/>
        System.out.println("fuck fuck fuck me ");
      }
    
      @Before("performance()")
      public void takeSeats() { //<co id="co_takeSeatsBefore"/>
        System.out.println("2222The audience is taking their seats.");
      }
    
      @Before("performance()")
      public void turnOffCellPhones() { //<co id="co_turnOffCellPhonesBefore"/>
        System.out.println("The audience is turning off their cellphones");
      }
    
      @AfterReturning("performance()")
      public void applaud() { //<co id="co_applaudAfter"/>
        System.out.println("CLAP CLAP CLAP CLAP CLAP");
      }
    
      @AfterThrowing("performance()")
      public void demandRefund() { //<co id="co_demandRefundAfterException"/>
        System.out.println("Boo! We want our money back!");
      }
    }

    Performer(被织入实现类的接口)

    package com.springinaction.springidol;
    
    public interface Performer {
      void perform() throws PerformanceException;
    }
    

    PerformanceException

    package com.springinaction.springidol;
    
    public class PerformanceException extends Exception {
      private static final long serialVersionUID = 1L;
    
    }
    

    Instrumentalist(被织入实现类的接口)

    package com.springinaction.springidol;
    
    public class Instrumentalist implements Performer {
      public void perform() throws PerformanceException {
        instrument.play();
      }
    
      private Instrument instrument;
    
      public void setInstrument(Instrument instrument) {
        this.instrument = instrument;
      }
    
      public Instrument getInstrument() {
        return instrument;
      }
    }
    

    测试类

    package com.springinaction.springidol;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.ApplicationContext;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("spring-idol.xml")
    public class AspectTest {
      @Autowired
      ApplicationContext context;
    
      @Test
      public void audienceShouldApplaud() throws Exception {
        Performer eddie = (Performer) context.getBean("eddie");
        eddie.perform();
      }
    
      @Test
      public void eddieShouldBeAContestant() {
        Contestant eddie = (Contestant) context.getBean("eddie");
        eddie.receiveAward();
      }
    }
    

    Maven的依赖

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>com.frank</groupId>
      <artifactId>springinaction</artifactId>
      <packaging>war</packaging>
      <version>1.0-SNAPSHOT</version>
      <name>springinaction Maven Webapp</name>
      <url>http://maven.apache.org</url>
    
    
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <springversion>3.1.1.RELEASE</springversion>
        <junitversion>3.8.1</junitversion>
      </properties>
      <dependencies>
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>3.8.1</version>
          <scope>test</scope>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aop</artifactId>
          <version>${springversion}</version>
          <type>jar</type>
          <scope>compile</scope>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-asm</artifactId>
          <version>${springversion}</version>
          <type>jar</type>
          <scope>compile</scope>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aspects</artifactId>
          <version>${springversion}</version>
          <type>jar</type>
          <scope>compile</scope>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-beans</artifactId>
          <version>${springversion}</version>
          <type>jar</type>
          <scope>compile</scope>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>${springversion}</version>
          <type>jar</type>
          <scope>compile</scope>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context-support</artifactId>
          <version>${springversion}</version>
          <type>jar</type>
          <scope>compile</scope>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-core</artifactId>
          <version>${springversion}</version>
          <type>jar</type>
          <scope>compile</scope>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-expression</artifactId>
          <version>${springversion}</version>
          <type>jar</type>
          <scope>compile</scope>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-jdbc</artifactId>
          <version>${springversion}</version>
          <type>jar</type>
          <scope>compile</scope>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aop</artifactId>
          <version>${springversion}</version>
        </dependency>
        <dependency>
          <groupId>org.aspectj</groupId>
          <artifactId>aspectjrt</artifactId>
          <version>1.8.2</version>
        </dependency>
        <dependency>
          <groupId>org.aspectj</groupId>
          <artifactId>aspectjweaver</artifactId>
          <version>1.8.2</version>
          <scope>runtime</scope>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-jms</artifactId>
          <version>${springversion}</version>
          <type>jar</type>
          <scope>compile</scope>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-orm</artifactId>
          <version>${springversion}</version>
          <type>jar</type>
          <scope>compile</scope>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-oxm</artifactId>
          <version>${springversion}</version>
          <type>jar</type>
          <scope>compile</scope>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-tx</artifactId>
          <version>${springversion}</version>
          <type>jar</type>
          <scope>compile</scope>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-web</artifactId>
          <version>${springversion}</version>
          <type>jar</type>
          <scope>compile</scope>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-webmvc</artifactId>
          <version>${springversion}</version>
          <type>jar</type>
          <scope>compile</scope>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-test</artifactId>
          <version>${springversion}</version>
          <type>jar</type>
          <scope>compile</scope>
        </dependency>
    
        <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>jstl</artifactId>
          <version>1.2</version>
          <type>jar</type>
          <scope>compile</scope>
        </dependency>
    
        <dependency>
          <groupId>commons-collections</groupId>
          <artifactId>commons-collections</artifactId>
          <version>3.1</version>
        </dependency>
    
        <dependency>
          <groupId>commons-logging</groupId>
          <artifactId>commons-logging</artifactId>
          <version>1.1</version>
        </dependency>
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>RELEASE</version>
          <scope>test</scope>
        </dependency>
      </dependencies>
    </project>

    运行的结果

    这里写图片描述

  • 相关阅读:
    linux驱动开发学习一:创建一个字符设备
    如何高效的对有序数组去重
    找到缺失的第一个正整数
    .NET不可变集合已经正式发布
    中国人唯一不认可的成功——就是家庭的和睦,人生的平淡【转】
    自己动手搭建 MongoDB 环境,并建立一个 .NET HelloWorld 程序测试
    ASP.NET MVC 中如何用自定义 Handler 来处理来自 AJAX 请求的 HttpRequestValidationException 错误
    自己动手搭建 Redis 环境,并建立一个 .NET HelloWorld 程序测试
    ServiceStack 介绍
    一步一步实战扩展 ASP.NET Route,实现小写 URL、个性化 URL
  • 原文地址:https://www.cnblogs.com/shugen/p/6863008.html
Copyright © 2011-2022 走看看