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>
运行的结果
Spring切面通知执行的顺序(Advice Order)的更多相关文章
- spring通知执行的顺序
点击下载本示例相关代码 关于spring aop的具体使用,暂时不在这里讲解,后面会特定来讲解,本次主要探讨spring中通知执行的顺序. spring中通知分为以下几种: before:前置通知,在 ...
- java随笔3 spring 的注入执行逻辑顺序
- 【原】Order属性决定了不同切面类中通知执行的先后顺序
[障碍再现] MyBatis配置多数据源时,数据源切换失败. [原因分析] 自定义切面和Spring自带事务切面“即<aop:advisor>”执行的先后顺序导致数据源不能切换成功. ...
- 【原】不定义Order属性,通过切面类的定义顺序来决定通知执行的先后顺序
[结论] 在多个切面类的“切入点相同”并且每个切面都“没有定义order属性”的情况下,则切面类(中的通知)的执行顺序与该切面类在<aop:config>元素中“声明的顺序”相关,即先声明 ...
- 浅谈Spring AOP 面向切面编程 最通俗易懂的画图理解AOP、AOP通知执行顺序~
简介 我们都知道,Spring 框架作为后端主流框架之一,最有特点的三部分就是IOC控制反转.依赖注入.以及AOP切面.当然AOP作为一个Spring 的重要组成模块,当然IOC是不依赖于Spring ...
- 关于spring.net的面向切面编程 (Aspect Oriented Programming with Spring.NET)-通知(Advice)API
本文翻译自Spring.NET官方文档Version 1.3.2. 受限于个人知识水平,有些地方翻译可能不准确,但是我还是希望我的这些微薄的努力能为他人提供帮助. 侵删. 让我们看看 Spring.N ...
- Spring系列26:Spring AOP 通知与顺序详解
本文内容 如何声明通知 如何传递参数到通知方法中 多种通知多个切面的通知顺序 多个切面通知的顺序源码分析与图解 声明通知 Spring中有5种通知,通过对应的注解来声明: @BeforeBefore ...
- spring多个AOP执行先后顺序(面试问题:怎么控制多个aop的执行循序)
转载:spring多个AOP执行先后顺序(面试问题:怎么控制多个aop的执行循序) 众所周知,spring声明式事务是基于AOP实现的,那么,如果我们在同一个方法自定义多个AOP,我们如何指定他们的执 ...
- Spring学习(十五)----- Spring AOP通知实例 – Advice
Spring AOP(面向方面编程)框架,用于在模块化方面的横切关注点.简单得说,它只是一个拦截器拦截一些过程,例如,当一个方法执行,Spring AOP 可以劫持一个执行的方法,在方法执行之前或之后 ...
随机推荐
- zoom动画,实现图片点击预览效果
参考:https://developer.android.google.cn/training/animation/zoom.html 1.创建Views 下面的布局包括了你想要zoom的大版本和小版 ...
- ORACLE JOB创建
Connected Connected as focususer SQL> SQL> --JOB 需要在命令行执行: SQL> --抽数job SQL> CREATE OR R ...
- 一些CSS/JS小技巧
CSS部分 1.文本框不可点击 .inputDisabled{ background-color: #eee;cursor: not-allowed;} 2.禁止复制粘贴 onpaste=" ...
- 开源的C#实现WebSocket协议客户端和服务器websocket-sharp组件解析
很久没有写博客了(至少自己感觉很长时间没有写了),没办法啊,楼主也是需要生活的人啊,这段一直都在找工作什么的.(整天催我代码的人,还望多多谅解啊,我会坚持写我们的项目的,还是需要相信我的,毕竟这是一个 ...
- Angular.js学习笔记 (二)
用A链接对象解析url的组成 var url = 'https://www.baidu.com:8080/aaa/1.html?id=10#name'; var aLink = document.cr ...
- css高级选择器
并集选择器 p,h1{} 交集选择器 p.first{} 后代选择器:嵌套标签 h1 span{} 子元素选择器 h1>span{} 属性选择器 input[type="passwor ...
- MyRocks DDL原理
最近一个日常实例在做DDL过程中,直接把数据库给干趴下了,问题还是比较严重的,于是赶紧排查问题,撸了下crash堆栈和alert日志,发现是在去除唯一约束的场景下,MyRocks存在一个严重的bug, ...
- 【HDOJ 1086】 模板水过
You can Solve a Geometry Problem too Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/3 ...
- redis 数据库实现
redis 数据库实现 数据库的 server 端和 client 端 server 端 数据库在 server 端的存储 // redisServer 结构 struct redisServer { ...
- centos7 下nfs的配置
td p { margin-bottom: 0cm } p { margin-bottom: 0.25cm; line-height: 120% } a:link { } 补充知识: RPC 主程序: ...