在Spring的AOP配置命名空间中,我们能够找到声明式切面选择。看以下:

	<aop:config>					<!-- AOP定义開始 -->
<aop:pointcut/> <!-- 定义切入点 -->
<aop:advisor/> <!-- 定义AOP通知器 -->
<aop:aspect> <!-- 定义切面開始 -->
<aop:pointcut/> <!-- 定义切入点 -->
<aop:before/> <!-- 前置通知 -->
<aop:after-returning/> <!-- 后置返回通知 -->
<aop:after-throwing/> <!-- 后置异常通知 -->
<aop:after/> <!-- 后置通知(无论通知的方法是否运行成功) -->
<aop:around/> <!-- 围绕通知 -->
<aop:declare-parents/> <!-- 引入通知 -->
</aop:aspect> <!-- 定义切面结束 -->
</aop:config> <!-- AOP定义结束 -->

一、声明切面

切面就是包括切入点和通知的对象,在Spring容器中将被定义为一个Bean。Schema方式的切面须要一个切面支持Bean,该支持Bean的字段和方法提供了切面的状态和行为信息,并通过配置方式来指定切入点和通知实现。

切面使用<aop:aspect>标签指定,ref属性用来引用切面支持Bean。

切面支持Bean“aspectSupportBean”跟普通Bean全然一样使用。切面使用“ref”属性引用它。

二、  声明切入点

切入点在Spring中也是一个Bean。Bean定义方式能够有非常三种方式:

1)在<aop:config>标签下使用<aop:pointcut>声明一个切入点Bean,该切入点能够被多个切面使用。对于须要共享使用的切入点最好使用该方式,该切入点使用id属性指定Bean名字。在通知定义时使用pointcut-ref属性通过该id引用切入点。expression属性指定切入点表达式:

<aop:config>
<aop:pointcut expression="execution(* cn.com.ztz.spring.service.ShowServiceImpl.*(..))" id="pointcut"/>
<aop:aspect ref="audienceAspect" >
<aop:before pointcut-ref="pointcut" method="taskSeats"/>
</aop:aspect>
</aop:config>

2)在<aop:aspect>标签下使用<aop:pointcut>声明一个切入点Bean,该切入点能够被多个切面使用,但一般该切入点仅仅被该切面使用,当然也能够被其它切面使用,但最好不要那样使用,该切入点使用id属性指定Bean名字,在通知定义时使用pointcut-ref属性通过该id引用切入点。expression属性指定切入点表达式:

	<aop:config>
<aop:aspect ref="audienceAspect" >
<aop:pointcut expression="execution(* cn.com.ztz.spring.service.ShowServiceImpl.*(..))" id="pointcut"/>
<aop:before pointcut-ref="pointcut" method="taskSeats"/>
</aop:aspect>
</aop:config>

3)匿名切入点Bean。能够在声明通知时通过pointcut属性指定切入点表达式,该切入点是匿名切入点,仅仅被该通知使用:

	<aop:config>
<aop:aspect ref="audienceAspect" >
<aop:before pointcut="execution(* cn.com.ztz.spring.service.ShowServiceImpl.*(..))" method="taskSeats"/>
</aop:aspect>
</aop:config>

三、   声明通知

直接来看个样例:
package cn.com.ztz.spring.service;

public interface ShowService {
public void show();
}
package cn.com.ztz.spring.service;

public class ShowServiceImpl implements ShowService{
@Override
public void show() {
showBefore();
//showError();//异常測试
showEnd();
}
public void showBefore(){
System.out.println("showBefore============");
}
public void showError(){
System.out.println("showError============");
throw new RuntimeException();
}
public void showEnd(){
System.out.println("showEnd===============");
}
}
package cn.com.ztz.spring.service;
public class AudienceAspect {
public void taskSeats(){
System.out.println("等候节目開始===");
}
public void applaud(){
System.out.println("鼓掌=========");
}
public void demandRefund(){
System.out.println("退钱离场======");
}
}
   <bean id="showService" class="cn.com.ztz.spring.service.ShowServiceImpl"/>
<bean id="audienceAspect" class="cn.com.ztz.spring.service.AudienceAspect"/>
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* cn.com.ztz.spring.service.ShowServiceImpl.*(..))"/>
<aop:aspect ref="audienceAspect" >
<aop:before pointcut-ref="pointcut" method="taskSeats"/>
<aop:after-returning pointcut-ref="pointcut" method="applaud"/>
<aop:after-throwing pointcut-ref="pointcut" method="demandRefund"/>
</aop:aspect>
</aop:config>
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
ShowService hs = ctx.getBean("showService", ShowService.class);
System.out.println("======================================");
hs.show();
System.out.println("======================================");
}

控制台输出结果:

======================================

等候节目開始===

showBefore============

showEnd===============

鼓掌=========

======================================

四、 为通知传递參数

如今有非常多人在观看演出,我想传入一个人姓名,怎么办了。来看下:
public interface ShowService {
public void showBefore(String param);
}
public class ShowServiceImpl implements ShowService{
public void showBefore(String param){
System.out.println("showBefore============");
}
}
<pre name="code" class="java">public class AudienceAspect {
public void taskSeats(String param){
System.out.println(param+",等候节目開始===");
}
}

   <bean id="showService" class="cn.com.ztz.spring.service.ShowServiceImpl"/>
<bean id="audienceAspect" class="cn.com.ztz.spring.service.AudienceAspect"/>
<aop:config>
<aop:aspect ref="audienceAspect" >
<aop:before pointcut="execution(* cn.com.ztz.spring.service.ShowServiceImpl.*(..)) and args(param)"
method="taskSeats(java.lang.String)"
arg-names="param"/>
</aop:aspect>
</aop:config>
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
ShowService hs = ctx.getBean("showService", ShowService.class);
System.out.println("======================================");
hs.showBefore("张三");
System.out.println("======================================");
}

控制台输出结果:

======================================

张三,等候节目開始===

showBefore============

======================================

五、  声明围绕通知

围绕着在切入点选择的连接点处的方法所运行的通知。围绕通知很强大,能够决定目标方法是否运行,什么时候运行,运行时是否须要替换方法參数,运行完成是否须要替换返回值,可通过<aop:aspect>标签下的<aop:around >标签声明:

围绕通知第一个參数必须是org.aspectj.lang.ProceedingJoinPoint类型,在通知实现方法内部使用ProceedingJoinPoint的proceed()方法使目标方法运行。proceed
方法能够传入可选的Object[]数组,该数组的值将被作为目标方法运行时的參数。
public interface ShowService {
public void showAround(String param);
}
public class ShowServiceImpl implements ShowService{
public void showAround(String param){
System.out.println("showAround============"+param);
}
}
public class AudienceAspect {
public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("around before advice===========");
Object retVal = pjp.proceed(new Object[] {"around"});
System.out.println("around after advice===========");
return retVal;
}
}
   	<bean id="showService" class="cn.com.ztz.spring.service.ShowServiceImpl"/>
<bean id="audienceAspect" class="cn.com.ztz.spring.service.AudienceAspect"/>
<aop:config>
<aop:aspect ref="audienceAspect" >
<aop:around pointcut="execution(* cn.com.ztz.spring.service.ShowServiceImpl.*(..))"
method="aroundAdvice"/>
</aop:aspect>
</aop:config>
public static void main(String[] args) {
<span style="white-space:pre"> </span>ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
ShowService hs = ctx.getBean("showService", ShowService.class);
System.out.println("======================================");
hs.showAround("张三");
System.out.println("======================================");
}

控制台输出结果:

======================================

around before advice===========

showAround============around

around after advice===========

======================================

六、引入

一些编程语言。比如Ruby和Groovy。有开放类的理念。

它们可以不用直接改动对象或类的定义可以为对象或类添加新的方法。不幸的是。java不是动态的语言,一旦编译完毕了。我们非常难再为该类加入新的功能了。

自己想想我们如今不是一直在用切面吗?实际上,利用被称为引入的AOP概念。切面能够为spring bean加入新的方法。

 Spring引入同意为目标对象引入新的接口,通过在< aop:aspect>标签内使用< aop:declare-parents>标签进行引入。



<aop:declare-parents  

          types-matching="AspectJ语法类型表达式"  

          implement-interface=引入的接口"               

          default-impl="引入接口的默认实现"  

          delegate-ref="引入接口的默认实现Bean引用"/>

看下样例:我们定义了个新的接口和实现
public interface DeclareService {
public void declare();
}
public class DeclareServiceImpl implements DeclareService {
@Override
public void declare() {
System.out.println("declare=====================");
}
}
   	<bean id="showService" class="cn.com.ztz.spring.service.ShowServiceImpl"/>
<bean id="declareService" class="cn.com.ztz.spring.service.DeclareServiceImpl"/>
<aop:config>
<aop:aspect>
<aop:declare-parents types-matching="cn.com.ztz.spring.service.ShowServiceImpl+"
implement-interface="cn.com.ztz.spring.service.DeclareService"
delegate-ref="declareService"/>
</aop:aspect>
</aop:config>
	public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
DeclareService hs = ctx.getBean("showService", DeclareService.class);
System.out.println("======================================");
hs.declare();
System.out.println("======================================");
}

我们获得还是showService的Bean,执行下測试方法输出结果:

======================================

declare=====================

======================================

Spring 在XML中声明切面/AOP的更多相关文章

  1. Spring AOP 在XML中声明切面

    转载地址:http://www.jianshu.com/p/43a0bc21805f 在XML中将一个Java类配置成一个切面: AOP元素 用途 <aop:advisor> 定义AOP通 ...

  2. 笔记11 在XML中声明切面(2)

    为通知传递参数 1.声明一个CompactDiscs接口.内部包含两个方法: show() 用于显示唱片的名字和艺术风格 playTrack(int number) 根据传入的磁道数播放相应磁道的音乐 ...

  3. 笔记10 在XML中声明切面(1)

    1.无注解的Audience package XMLconcert; public class Audience { public void silenceCellPhones() { System. ...

  4. spring的xml配置声明以及相应的问题处理

    spring的xml配置声明:  xml配置声明 Code 问题处理 问题1 xml报错: cvc-elt.1: Cannot find the declaration of element 'bea ...

  5. SPRING IN ACTION 第4版笔记-第七章Advanced Spring MVC-002- 在xml中引用Java配置文件,声明DispatcherServlet、ContextLoaderListener

    一.所有声明都用xml 1. <?xml version="1.0" encoding="UTF-8"?> <web-app version= ...

  6. Spring框架系列(五)--面向切面AOP

    背景: 当需要为多个不具有继承关系的对象引入一个公共行为,例如日志.权限验证.事务等功能时,如果使用OOP,需要为每个对象引入这些公共 行为.会产生大量重复代码,并且不利用维护.AOP就是为了解决这个 ...

  7. Spring基础(二)_面向切面(AOP)

    面向切面编程 面向切面编程[AOP,Aspect Oriented Programming]:通过预编译方式和运行期间动态代理实现程序功能的统一维护的技术.AOP 是 Spring 框架中的一个重要内 ...

  8. 在IDEA 、springboot中使用切面aop实现日志信息的记录到数据库

    文章目录 1.导入相关的依赖 2.创建要保存的数据信息实体类 3 .编写对应的sql语句 4.使用spring 的 aop 技术切到自定义注解上,所以先创建一个自定义注解类 5. 创建aop切面实现类 ...

  9. Spring web.xml中的配置

    转载博客:http://blog.163.com/zhangke_616/blog/static/191980492007994948206/ 在实际项目中spring的配置文件application ...

随机推荐

  1. NOIP差不多可以退役的退役记录

    好吧,现在既然苟回来了,就来回忆一下我NOIP2017的黑历史吧. Day-1: 原本以为是很平静的一天,上午学考机房强行断网,原因是腾出网速给对面学考的同学们查资料用.好吧没法刷题我只能选择颓废…… ...

  2. hdu 4859 最小割

    链接:点我 未懂

  3. hierarchyid有关的一些函数

    于hierarchyid有关的一些函数主要有:    GetAncestor :取得某一个级别的祖先    GetDescendant :取得某一个级别的子代    GetLevel :取得级别    ...

  4. 从零开始搭建linux下laravel 5.5所需环境(三)

    好的,我们已经安装好了nginx+mysql+php了,打开[ Laravel 5.5 文档 ] 快速入门 —— 安装配置篇 我们看到这里需要安装Composer,好的,我们现在就来安装Compose ...

  5. BZOJ 1500: [NOI2005]维修数列 (splay tree)

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 4229  Solved: 1283[Submit][Status ...

  6. 将代码库从 SVN 迁移至 Git 并保留所有 commit 记录

    公司内部原本使用 SVN 进行版本控制,但随着 Github 的流行我个人的代码管理习惯逐渐转变.虽然公司项目并非开源,SVN 所具有的标准 trunk / branches / tags 结构完全够 ...

  7. 斑马Zebra驱动下载

    Zebra GT800 点击进入下载页-> 自动安装包[WINXP/WIN7/WIN8]点击进入下载页-> 添加打印机向导[WINXP/WIN7/WIN8]   热门下载 · Zebra ...

  8. datagrid在MVC中的运用08-实现Master-Detail(使用子datagrid)

    本文主要通过一个子datagrid来实现主次表.谢谢Kevin的博文. 代码部分与http://www.cnblogs.com/darrenji/p/3576258.html相似,这里只列出不一样的地 ...

  9. QDAC

    QDAC GITHUB: svn://www.qdac.cc/QDAC3 包括QMsgPack\QJson\QWoker...等序列和事件调度控件.

  10. 转 iOS 调试技巧

    调度技巧一: 程序在崩溃的时候,xcode经常没有给出准确的堆栈信息,而是定位在了main方法里,这个让人很是头疼,又怀念起了vs, 其实xcode只要装简单设置一下,就能准确给出堆栈信息了,  打开 ...