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切面的文件
下面用一個例項來說明如何執行多個通知,例項採用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>