Spring的AOP模块.docx
- 文档编号:16970630
- 上传时间:2023-07-20
- 格式:DOCX
- 页数:12
- 大小:34.11KB
Spring的AOP模块.docx
《Spring的AOP模块.docx》由会员分享,可在线阅读,更多相关《Spring的AOP模块.docx(12页珍藏版)》请在冰点文库上搜索。
Spring的AOP模块
第3章Spring的AOP模块
本章学习目的和要求
本章重点和难点
AOP是Spring框架的另一个重要特征。
AOP(AspectOrientedProgramming,面向切面编程)把一个业务流程分成几部分,例如权限检查、业务处理、日志记录,每个部分单独处理,然后把它们组装成完整的业务流程。
每个部分被称为切面(Aspect)或者关注点。
3.1实例:
使用拦截器拦截方法(在struts-2.3.8中复制commons-logging-1.1.1、aopalliance-1.0.jar)
AOP有一些重要的概念,包括切面(Aspect)、连接点(Joinpoint)、通知(Advice)、切入点(Pointcut)、引用(Introduction)等。
这些概念并不是Spring定义的。
对于刚刚接触AOP的开发者来说,这些概念非常抽象,往往很难理解。
抛开这些抽象的概念,先来看一个AOP例子。
前面的章节中曾介绍了一个AOP的例子。
下面看一下稍微复杂的例子。
本例中,AOP的规则要稍微复杂一些。
3.1.1Service接口
Spring推荐使用接口编程。
该接口定义了两个方法。
一会儿将使用拦截器拦截其中的withAop()方法,而另一个方法withoutAop()将不会被拦截。
IAopService.java
packagecom.helloweenvsfei.spring.aop;
publicinterfaceIAopService
{//Service接口,定义两个方法
publicvoidwithAop()throwsException;//将会被拦截
publicvoidwithoutAop()throwsException;//不会被拦截
}
3.1.2Service实现代码
IAopService实现类中定义了一个name属性,以及对应的getter、setter方法。
实现类代码为:
AopServiceImpl.java
packagecom.helloweenvsfei.spring.aop;
importjavax.security.auth.login.AccountException;
publicclassAopServiceImplimplementsIAopService
{
//Service实现
privateStringname;//name属性
publicvoidwithAop()throwsException
{
//withAop方法实现
System.out.println("有AOP的函数运行。
name:
"+name);
if(name.trim().length()==0)//如果name为空
thrownewAccountException("name属性不能为空");//则抛出异常
}
publicvoidwithoutAop()throwsException
{
//withoutAop方法实现
System.out.println("没有AOP的函数运行。
");
}
publicStringgetName()
{
//getter方法
returnname;
}
publicvoidsetName(Stringname)
{
//setter方法
this.name=name;
}
}
3.1.3方法前拦截器检查name是否为null
下面是方法前拦截器,实现自MethodBeforeAdvice接口。
方法前拦截器在执行指定方法前被调用,参数分别为被调用的方法、执行时被传入的参数、被拦截的Bean。
代码为:
MethodBeforeInterceptor.java
packagecom.helloweenvsfei.spring.aop;
importjava.lang.reflect.Method;
importorg.springframework.aop.MethodBeforeAdvice;
publicclassMethodBeforeInterceptorimplementsMethodBeforeAdvice
{
//方法前拦截器
//调用对象的方法前将执行该方法。
参数分别为被调用的方法、被调用调用方法的参数、对象
publicvoidbefore(Methodmethod,Object[]args,Objectinstance)throwsThrowable
{
System.out.println("即将要执行方法:
"+method.getName());//打印控制台
if(instanceinstanceofAopServiceImpl)
{
//如果是Service
Stringname=((AopServiceImpl)instance).getName();//获取name
if(name==null)//检查是否为空
thrownewNullPointerException("name属性不能为null");
}
}
}
3.1.4返回后拦截器输出返回值
返回后拦截器,实现自AfterReturningAdvice接口。
返回后拦截器在执行完指定方法、并返回之后被调用。
如果有返回值,可以取到返回值,否则为null。
参数分别为方法返回值、被调用的方法、执行时被传入的参数、被拦截的Bean。
代码为:
MethodAfterInterceptor.java
packagecom.helloweenvsfei.spring.aop;
importjava.lang.reflect.Method;
importorg.springframework.aop.AfterReturningAdvice;
publicclassMethodAfterInterceptorimplementsAfterReturningAdvice
{
//方法后拦截器
publicvoidafterReturning(Objectvalue,Methodmethod,Object[]args,Objectinstance)throwsThrowable
{
System.out.println("方法"+method.getName()+"运行完毕,返回值为:
"+value);
}
}
3.1.5异常拦截器捕获异常
异常抛出拦截器,实现自ThrowsAdvice接口。
如果指定的方法中有异常被抛出,被调用。
与上两个拦截器接口不同,ThrowsAdvice接口没有定义任何方法,因此不需要实现任何方法。
但是如果定义了形如
afterThrowing([Method],[args],[target],subclassOfThrowable)
的方法,这些方法将会被调用。
参数分别为:
被调用的方法、方法的参数、被拦截的Bean以及抛出的异常类。
这里面只有最后一个参数是必须的。
Spring之所以这样设计,是为了是开发者灵活的定义多个方法捕捉不同的异常。
代码为:
packagecom.helloweenvsfei.spring.aop;
importjava.lang.reflect.Method;
importjavax.security.auth.login.AccountException;
importorg.springframework.aop.ThrowsAdvice;
publicclassThrowsInterceptorimplementsThrowsAdvice
{
//异常拦截器
publicvoidafterThrowing(Methodmethod,Object[]args,Objectinstance,AccountExceptionex)throwsThrowable
{
System.out.println("方法"+method.getName()+"抛出了异常:
"+ex);
}
publicvoidafterThrowing(NullPointerExceptionex)throwsThrowable
{
System.out.println("抛出了异常:
"+ex);
}
}
3.1.6拦截器配置
然后把三个拦截器连同Service实现类配置到Spring中。
Spring将实例化三个拦截器对象、一个Service对象,并安装指定的规则装配。
配置代码为:
ApplicationContext.xml
xmlversion="1.0"encoding="UTF-8"?
>
//www.springframework.org/schema/beans" xmlns: xsi="http: //www.w3.org/2001/XMLSchema-instance" xsi: schemaLocation="http: //www.springframework.org/schema/beanshttp: //www.springframework.org/schema/beans/spring-beans-2.0.xsd"> --拦截器在withAop()方法前运行--> --拦截器在withAop()返回后运行--> class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor"> --拦截器在异常抛出后运行--> class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor"> class="org.springframework.aop.framework.ProxyFactoryBean"> --拦截器--> --被拦截的对象--> 3.1.7运行代码 运行代码从Spring容器中获取Service对象,并分别执行Service的两个方法withAop()与withoutAop()。 Spring将会在withAop()方法前后添加拦截器,但withoutAop()方法前后不会。 代码为: AopRun.java packagecom.helloweenvsfei.spring.aop; importorg.springframework.beans.factory.xml.XmlBeanFactory; importorg.springframework.core.io.ClassPathResource; publicclassAopRun { publicstaticvoidmain(String[]args)throwsException{ XmlBeanFactoryfactory=newXmlBeanFactory(//获取Factory newClassPathResource("applicationContext.xml")); IAopServicehello=(IAopService)factory.getBean("aopService");//查找对象 hello.withAop();//执行withAop() hello.withoutAop();//执行withoutAop() factory.destroySingletons();//销毁对象 } } 运行效果如图3.1。 图3.1拦截器运行效果 在本例中,由于没有异常抛出,因此ThrowsInterceptor没有起作用。 读者可以在xml中设置name属性为null或者空字符串,使withAop()方法中抛出异常,观察运行效果。 3.2拦截器与Filter的区别 Spring的拦截器与Servlet的Filter有相似之处,比如二者都是AOP编程思想的体现,都能实现权限检查、日志记录等。 不同的是: 3.2.1使用范围不同 Filter是Servlet规范规定的,只能用于Web程序中。 而拦截器即可以用于Web程序,也可以用于Application、Swing程序中。 3.2.2规范不同 Filter是在Servlet规范中定义的,是Servlet容器支持的。 而拦截器是在Spring容器内的,是Spring框架支持的。 3.2.3使用的资源不同 同其它的代码块一样,拦截器也是一个Spring的组件,归Spring管理,配置在Spring文件中,因此能使用Spring里的任何资源、对象,例如Service对象、数据源、事务管理等,通过IoC注入到拦截器即可;而Filter则不能。 3.2.4深度不同 Filter在只在Servlet前后起作用。 而拦截器能够深入到方法前后、异常抛出前后等,因此拦截器的使用具有更大的弹性。 因此在Spring构架的程序中,要优先使用拦截器。 3.3AOP的相关概念 看一下面向切面的编程的几个常用的概念: 切面Aspect、通知Advisor与切入点Pointcut。 3.3.1切面Aspect 在本例中,方法withAop()、withoutAop()中都有一些代码。 虽然只是一些输出语句,但是在真实的程序中这里应该是一些有意义的代码(如读写数据库、权限检查、异常情况记录等)。 这些代码可以看作是AOP中的切面(Aspect)。 可以将切面理解为模块。 3.2.2通知Advisor 本例的三个拦截器都是实现自某个Advisor接口。 从类名上看就知道三个拦截器都是AOP中的通知(Advisor)。 一旦Spring符合条件,就会派发出通知。 与生活中的通知不同的地方在于,Spring中的通知是带有执行代码的,实现某种功能。 3.3.3切入点Pointcut 在配置拦截器的时候,xml中只配置了withAop()方法使用拦截器,而withoutAop()方法没有配置拦截器。 这种配置是借助于org.springframework.aop.support.NameMatchMethodPointcutAdvisor完成的。 从类名称上看,这是一个切入点(Pointcut)。 该类对象能配置对哪些方法使用拦截器,从哪个地方“切入”进去。 配置时可以使用通配符。 该类名上也带有Advisor是因为它是用通知(Advisor)实现的。 简单地说,“切入点”负责往“什么地方”插入代码,而“通知”负责插入“什么代码”。 3.3.4切入点配置方式 Spring提供灵活的切入点配置方式。 例如使用正则表达式。 下面是Spring官方的一个使用正则表达式的例子。 Spring接受Perl5支持的正则表达式: class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> --切入点--> --拦截器--> --正则表达式配置切入点--> --包含get的方法--> --包含absquatulate的方法--> 3.4AOP的代理模式 代理模式是Spring中常用的设计模式。 Spring提供了几个常用的代理类,例如普通的代理类、事务代理类等等。 3.4.1ProxyFactoryBean代理工厂对象 上例配置AopServiceImpl时使用了org.springframework.aop.framework.ProxyFactoryBean类。 这是Spring内置的代理类,引入了一个中间层,能够创建不同类型的对象。 利用它可以实现任何形式的AOP。 3.4.2TransactionProxyFactoryBean事务代理工厂对象 另一个很有用的代理类是TransactionProxyFactoryBean,是ProxyFactoryBean的子类,常用在数据库编程上。 Spring利用TransactionProxyFactoryBean对事务进行管理,在指定方法前利用AOP连接数据库并开启事务,然后在指定方法返回后利用AOP提交事务并断开数据库。 例如Spring宠物商店里的事务性配置: class="org.springframework.samples.jpetstore.domain.logic.PetStoreImpl"> --其余的配置略--> class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> 事务管理配置详见本章后面的DAO模块与ORM模块。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Spring AOP 模块