Spring AOP原理及拦截器Word格式.docx
- 文档编号:20589949
- 上传时间:2023-01-24
- 格式:DOCX
- 页数:17
- 大小:25.22KB
Spring AOP原理及拦截器Word格式.docx
《Spring AOP原理及拦截器Word格式.docx》由会员分享,可在线阅读,更多相关《Spring AOP原理及拦截器Word格式.docx(17页珍藏版)》请在冰豆网上搜索。
例如,你可以使用一个引入使任何对象实现IsModified接口,来简化缓存。
—目标对象(TargetObject):
包含连接点的对象,也被称作被通知或被代理对象。
—AOP代理(AOPProxy):
AOP框架创建的对象,包含通知。
在Spring中,AOP代理可以是JDK动态代理或CGLIB代理。
—编织(Weaving):
组装方面来创建一个被通知对象。
这可以在编译时完成(例如使用AspectJ编译器),也可以在运行时完成。
Spring和其他纯JavaAOP框架一样,在运行时完成织入。
各种通知类型包括:
—Around通知:
包围一个连接点的通知,如方法调用。
这是最强大的通知。
Aroud通知在方法调用前后完成自定义的行为,它们负责选择继续执行连接点或通过返回它们自己的返回值或抛出异常来短路执行。
—Before通知:
在一个连接点之前执行的通知,但这个通知不能阻止连接点前的执行(除非它抛出一个异常)。
—Throws通知:
在方法抛出异常时执行的通知。
Spring提供强制类型的Throws通知,因此你可以书写代码捕获感兴趣的异常(和它的子类),不需要从Throwable或Exception强制类型转换。
—Afterreturning通知:
在连接点正常完成后执行的通知,例如,一个方法正常返回,没有抛出异常。
Around通知是最通用的通知类型。
大部分基于拦截的AOP框架(如Nanning和Jboss4)只提供Around通知。
如同AspectJ,Spring提供所有类型的通知,我们推荐你使用最为合适的通知类型来实现需要的行为。
例如,如果只是需要用一个方法的返回值来更新缓存,你最好实现一个afterreturning通知,而不是around通知,虽然around通知也能完成同样的事情。
使用最合适的通知类型使编程模型变得简单,并能减少潜在错误。
例如,你不需要调用在around通知中所需使用的MethodInvocation的proceed()方法,因此就调用失败。
切入点的概念是AOP的关键,它使AOP区别于其他使用拦截的技术。
切入点使通知独立于OO的层次选定目标。
例如,提供声明式事务管理的around通知可以被应用到跨越多个对象的一组方法上。
因此切入点构成了AOP的结构要素。
拦截器(也称拦截机)
拦截机(Interceptor),是AOP(Aspect-OrientedProgramming)的另一种叫法。
AOP本身是一门语言,只不过我们使用的是基于JAVA的集成到Spring中的SpringAOP。
同样,我们将通过我们的例子来理解陌生的概念。
接口类
Java代码
packagecom.test.TestSpring3;
publicinterfaceUserService//被拦截的接口
...{
publicvoidprintUser(Stringuser);
}
实现类
publicclassUserServiceImpimplementsUserService//实现UserService接口
publicvoidprintUser(Stringuser)...{
System.out.println("
printUseruser:
"
+user);
//显示user
}
AOP拦截器
importorg.aopalliance.intercept.MethodInterceptor;
importorg.aopalliance.intercept.MethodInvocation;
publicclassUserInterceptorimplementsMethodInterceptor
//AOP方法拦截器
publicObjectinvoke(MethodInvocationarg0)throwsThrowable...{
try...{
if(arg0.getMethod().getName().equals("
printUser"
))
//拦截方法是否是UserService接口的printUser方法
...{
Object[]args=arg0.getArguments();
//被拦截的参数
user:
+args[0]);
arg0.getArguments()[0]="
hello!
;
//修改被拦截的参数
System.out.println(arg0.getMethod().getName()+"
---!
);
returnarg0.proceed();
//运行UserService接口的printUser方法
}catch(Exceptione)...{
throwe;
测试类
importorg.springframework.beans.factory.BeanFactory;
importorg.springframework.beans.factory.xml.XmlBeanFactory;
importorg.springframework.context.ApplicationContext;
importorg.springframework.context.support.ClassPathXmlApplicationContext;
importorg.springframework.context.support.FileSystemXmlApplicationContext;
importorg.springframework.core.io.ClassPathResource;
importorg.springframework.core.io.Resource;
importorg.springframework.web.context.support.WebApplicationContextUtils;
publicclassTestInterceptor...{
publicstaticvoidmain(String[]args)...{
ApplicationContextctx=newFileSystemXmlApplicationContext(
"
classpath:
applicationContext.xml"
//ApplicationContextctx=newClassPathXmlApplicationContext("
UserServiceus=(UserService)ctx.getBean("
userService"
us.printUser("
shawn"
}
配置文件
Xml代码
<
?
xmlversion="
1.0"
encoding="
UTF-8"
>
!
DOCTYPEbeansPUBLIC"
-//SPRING//DTDBEAN//EN"
http:
//www.springframework.org/dtd/spring-beans.dtd"
beans>
<
beanid="
userServiceImp"
class="
com.test.TestSpring3.UserServiceImp"
/>
userInterceptor"
com.test.TestSpring3.UserInterceptor"
org.springframework.aop.framework.ProxyFactoryBean"
--代理接口-->
propertyname="
proxyInterfaces"
value>
com.test.TestSpring3.UserService<
/value>
/property>
--目标实现类-->
target"
reflocal="
--拦截器-->
interceptorNames"
list>
userInterceptor<
/list>
/bean>
/beans>
输出:
user:
shawn
printUser---!
printUseruser:
结论:
调用方法的时候传入的值被拦截修改了.
拦截器中的事务管理(事务拦截机)
如果不采用拦截机的机制时,在使用JDBC进行数据库访问时,存在两种情况:
自动提交这是JDBC驱动默认的模式,每次数据库操作(CRUD)成功完成后,都作为一个单独的事务自动提交,如果未成功完成,即抛出了SQLException的话,仅最近的一个操作将回滚。
非自动提交这是想更好的控制事务时需要程序地方式进行控制:
在进行该事务单元的任何操作之前setAutoCommit(false)
在成功完成事务单元后commit()
在异常发生后rollback()
自动提交模式是不被推荐的,因为每个操作都将产生一个事务点,这对于大的应用来说性能将受到影响;
再有,对于常见的业务逻辑,这种模式显得无能为力。
比如:
转帐,从A帐户取出100元,将其存入B帐户;
如果在这两个操作之间发生了错误,那么用户A将损失了100元,而本来应该给帐户B的,却因为失败给了银行。
所以,建议在所有的应用中,如果使用JDBC都将不得不采用非自动提交模式(你们要能发现了在我们的JDBC那个例子中,我们采用的就是自动提交模式,我们是为了把精力放在JDBC上,而不是事务处理上),即我们不得不在每个方法中:
try{
//在获得连接后,立即通过调用 setAutoCommit(false)将事务处理置为非自动提交模式//PrepareQuerytofetchtheuserInformation
pst=conn.prepareStatement(findByName);
//...mit();
}catch(Exceptionex){
conn.rollback();
throwex;
}finally{
try{
//CloseResultSetandStatement
if(rset!
=null)rset.close();
if(pst!
=null)pst.close();
}catch(Exceptionex){
ex.printStackTrace();
thrownewException("
SQLErrorwhileclosingobjects="
+ex.toString());
这样代码在AOP的倡导者看来是“肮脏”的代码。
他们认为,所有的与事务有关的方法都应当可以集中配置(见声明性事务控制),并自动拦截,程序应当关心他们的主要任务,即商业逻辑,而不应和事务处理的代码搅和在一起。
我先看看Spring是怎么做到拦截的:
Spring内置支持的事务处理拦截机
这里因为要用到JpetStore项目中的代码,我们将applicationContext.xml全部内容列出:
--
-ApplicationcontextdefinitionforJPetStore'
sbusinesslayer.
-ContainsbeanreferencestothetransactionmanagerandtotheDAOsin
-dataAccessContext-local/jta.xml(seeweb.xml'
s"
contextConfigLocation"
).
Jpetstore的应用上下文定义,包含事务管理和引用了在dataAccessContext-local/jta.xml(具体使用了哪个要看web.xml中的'
contextConfigLocation'
的配置)中注册的DAO
-->
beansxmlns="
//www.springframework.org/schema/beans"
xmlns:
xsi="
//www.w3.org/2001/XMLSchema-instance"
aop="
//www.springframework.org/schema/aop"
tx="
//www.springframework.org/schema/tx"
xsi:
schemaLocation="
//www.springframework.org/schema/beanshttp:
//www.springframework.org/schema/beans/spring-beans-2.0.xsd
http:
//www.springframework.org/schema/aophttp:
//www.springframework.org/schema/aop/spring-aop-2.0.xsd
//www.springframework.org/schema/txhttp:
//www.springframework.org/schema/tx/spring-tx-2.0.xsd"
--=========================GENERALDEFINITIONS=========================-->
--Configurerthatreplaces${...}placeholderswithvaluesfrompropertiesfiles
占位符的值将从列出的属性文件中抽取出来
-->
--(inthiscase,mailandJDBCrelatedproperties)-->
propertyConfigurer"
org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
locations"
WEB-INF/mail.properties<
WEB-INF/jdbc.properties<
--MailSenderusedbyEmailAdvice
指定用于发送邮件的javamail实现者,这里使用了spring自带的实现。
此bean将被emailAdvice使用
mailSender"
org.springframework.mail.javamail.JavaMailSenderImpl"
host"
value="
${mail.host}"
/>
--=========================BUSINESSOBJECTDEFINITIONS========================-->
--不需要,因为被SpringMVC的实现使用GenericvalidatorforAccountobjects,tobeusedforexamplebytheSpringwebtier-->
accountValidator"
org.springframework.samples.jpetstore.domain.logic.AccountValidator"
--不需要,因为被SpringMVC的实现使用GenericvalidatorforOrderobjects,tobeusedforexamplebytheSpringwebtier-->
orderValidator"
org.springframework.samples.jpetstore.domain.logic.OrderValidator"
主要的商业逻辑对象,即我们所说的门面对象
注入了所有的DAO,这些DAO是引用了dataAccessContext-xxx.xml中定义的DAO
门面对象中的所有方法的事务控制将通过下面的aop:
config来加以控制
-JPetStoreprimarybusinessobject(defaultimplementation).
-TransactionadvicegetsappliedthroughtheAOPconfigurationbelow.
petStore"
org.springframework.samples.jpetstore.domain.logic.PetStoreImpl"
accountDao"
ref="
categoryDao"
productDao"
itemDao"
orderDao"
--=========================ASPECTCONFIGURATION========================-->
--AOP配置,用来控制哪些方法将需要进行事务处理,采用了AspectJ的语法-->
aop:
config>
Thisdefinitioncreatesauto-proxyinfrastructurebasedonthegivenpointcut,
expressedinAspectJpointcutlanguage.Here:
applyingtheadvicenamed
txAdvice"
toallmethodsonclassesnamedPetStoreImpl.
--指出在PetStoreFacade的所有方法都将采用txAdvice(在紧接着的元素中定义了)事务方针,注意,我们这里虽然指定的是接口PetStoreFacace,但其暗示着其所有的实现类也将
同样具有这种性质,因为本身就是实现类的方法在执行的,接口是没有方法体的。
advisorpointcut="
execution(**..PetStoreFacade.*(..))"
advice-ref="
expressedinAspectJpointcut
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Spring AOP原理及拦截器 AOP 原理 拦截