第7章 项目开发:日志输出和事务管理功能_第1页
第7章 项目开发:日志输出和事务管理功能_第2页
第7章 项目开发:日志输出和事务管理功能_第3页
第7章 项目开发:日志输出和事务管理功能_第4页
第7章 项目开发:日志输出和事务管理功能_第5页
已阅读5页,还剩53页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第第7章章项目开发:日志输出和事务管理项目开发:日志输出和事务管理功能功能7.1SpringAOP简介简介7.27.3开开发发步步骤骤知识点知识点Hibernate缓存、事务管理缓存、事务管理7.1SpringAOP简介简介7.1.1从代理机制初探从代理机制初探AOP下面来看一个简单的例子,它在执行某些方法时留下的日志信息如下:import java.util.logging.*;public class HelloSpeaker private Logger logger=Logger.getLogger(this.getClass().getName(); public void hell

2、o(String name) logger.log(Level.INFO, hello method starts);/方法执行开始时留下日志 System.out.println(hello, +name); /程序的主要功能 Logger.log(Level.INFO, hello method ends);/方法执行完毕时留下日志 7.1.1从代理机制初探从代理机制初探AOP举个简单的例子,首先定义一个Ihello接口。Ihello.java的代码如下:public interface Ihello public void hello(String name);然后让实现业务逻辑的Hel

3、loSpeaker类实现Ihello接口。HelloSpeaker.java的代码如下:public class HelloSpeaker implements Ihello public void hello(String name) System.out.println(hello, +name); 7.1.1从代理机制初探从代理机制初探AOPHelloProxy.java的代码如下:public class HelloProxy implements Ihello private Logger logger=Logger.getLogger(this.getClass().getName

4、(); private Ihello helloObject; public HelloProxy(Ihello helloObject) this.helloObject=helloObject; public void hello(String name) log(hello method starts);/开始日志服务 helloObject.hello(name);/执行业务逻辑 log(hello method ends);/结束日志服务 private void log(String msg) logger.log(Level.INFO,msg); 7.1.1从代理机制初探从代理机

5、制初探AOP在HelloProxy类的hello()方法中,真正实现了业务逻辑前后可以安排记录服务,可以实际撰写一个测试程序来看看如何使用代理类。public class ProxyDemo public static void main(String args) Ihello proxy=new HelloProxy(new HelloSpeaker(); proxy.hello(Justin); 7.1.2动态代理动态代理Ihello.java的代码如下:public interface Ihello public void hello(String name);HelloSpeaker.

6、java的代码如下:public class HelloSpeaker implements Ihello public void hello(String name) System.out.println(hello, +name); 7.1.2动态代理动态代理与静态代理不同的是,这里要实现不同的代理类:import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class LogHandler implements InvocationHandlerprivate Object sub;

7、public LogHandler()public LogHandler(Object obj)sub=obj;public Object invoke(Object proxy,Method method,Object args)throws ThrowableSystem.out.println(before you do thing);method.invoke(sub,args);System.out.println(after you do thing);return null;7.1.2动态代理动态代理ProxyDemo.java的代码如下:import java.lang.ref

8、lect.Proxypublic class ProxyDemo public static void main(String args) LogHandler logHandler=new LogHandler(); Ihello helloProxy=(Ihello)logHandler.bind(new HelloSpeaker(); helloProxy.hello(Justin); 7.1.3AOP基本概念基本概念 IoC以外Spring的另一个关键的组件就是AOP框架。尽管如此,Spring IoC容器并不依赖于AOP,这意味着可以自由选择是否使用AOP,AOP提供强大的中间件解决

9、方案,这使得Spring IoC容器更加完善。 面向切面编程(AOP)提供另外一种角度来思考程序结构,通过这种方式弥补了面向对象编程(OOP)的不足。 除了类(classes)以外,AOP提供了 切面。切面对关注点进行模块化,例如横切多个类型和对象的事务管理。(这些关注点术语通常称作横切(crosscutting)关注点。)AOP基本概念基本概念 AOP是一种流行的编程模型; AOP的编程思想与OOP不同,是对OOP的一种强有力的补充; 通过AOP,能更好地实现模块化结构,或者能动态地为系统增加新功能而不影响原系统的结构13SpringAOP 概述 AOP 允许开发者动态地修改OOP定义的静态

10、模型,即不用修改原来的OO模型,甚至可以不修改OO代码本身,即可完成对横切面问题的解决。 比如,将系统中处理日志、安全性、事务及其他企业级服务集中放置在一个地方。因此AOP使得OOP中的重复代码能够大范围减少。14SpringAOPSpringSpring就是一个实现了就是一个实现了AOPAOP功能的功能的IOCIOC容器容器15SpringAOP Sping AOP基于IoC,是对OOP的有益补充. Sping AOP将应用系统分为两部分,核心业务逻辑及横向的通用逻辑,即切面(Aspect)。比如大型应用中涉及的持久化管理、事务管理、安全管理、日志管理和调试管理。 使用AOP可以将处理Asp

11、ect的代码注入主程序,AOP可以防止代码混乱。167.1.3AOP基本概念基本概念AOP(Aspect-Oriented Programming,面向切面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当需要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。对于其他类型的代码,如安全性

12、、异常处理和透明的持续性也是如此。这种散布在各处的无关的代码被称为横切(cross-cutting)代码,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。7.1.3AOP基本概念基本概念1Cross-cuttingconcerns如图7.1所示,原来的业务流程是很单纯的。7.1.3AOP基本概念基本概念如图7.2所示,为了加入日志与安全检查等服务,类的程序代码中被硬生生地切入了相关的Logging、Security程序片段。AOP概述概述AOP(Aspect Oriented Programming)的背景知识 为满足整个企业应用某方面的需求,开发者(架构师)需要整理出系统的关

13、注点,如下图形象地描述了关注点。20比如:事务管理、安全性管理、应用的业务逻辑都是应用需要重点解决的问题。被作为关注点看待。整个系统由大量的关注点构成。一、一、AOP介绍介绍SpringAOP实现 Spring AOP使用纯Java实现。它不需要专门的编译过程, 不需要控制类装载器层次,因此它适用于J2EE web容器或应用服务器。 Spring目前仅支持使用方法调用作为连接点(join point). Spring的观点是属性拦截破坏了封装。 Spring实现AOP的方法跟其他的框架不同。Spring并不是要提供最完整的AOP实现(尽管Spring AOP有这个能力),相反的,它其实侧重于提

14、供一种AOP实现和Spring IoC容器之间的整合,用于帮助解决在企业级开发中的常见问题。 Spring使用动态代理实现AOP技术。AOP的意义的意义现在的系统往往强调减小模块之间的耦合度,AOP 技术就是用来帮助实现这一目标的。从某种角度上来讲“切面”是一个非常形象的描述,它好像在系统的功能之上横切一刀,要想让系统的功能继续,就必须先过了这个切面。这些切面监视并拦截系统的行为,在某些(被指定的)行为执行之前或之后执行一些附加的任务(比如记录日志)。而系统的功能流程(比如 Greeting)并不知道这些切面的存在,更不依赖于这些切面,这样就降低了系统模块之间的耦合度。 AOP的术语的术语 各

15、种AOP实现切面的技术、框架、机制、手段可能不同,但是AOP技术的基本概念是相同的。包括以下个术语: 连接点(连接点(join pointjoin point) 切入点(切入点(cutpoint)cutpoint) 通知(通知(adviceadvice) 引入(引入(introductionintroduction) 目标对象(目标对象(target objecttarget object) 织入(织入(weavingweaving) 切面(切面(AspectAspect)23AOP的术语的术语 连接点连接点(Joinpoint)(Joinpoint) 连接点指程序(目标对象)执行的某个点,如

16、执行到某个方法、访问到某个成员变量、抛出某异常、装载某个类。在Spring AOP中,一个连接点总是表示一个方法的执行。 通常用连接点的强弱来衡量AOP实现的强弱。Aspect5实现的连接点类型非常多,Spring AOP仅支持方法级连接点。24AOP的术语的术语 切入点(切入点(pointcutpointcut) 通过切入点能够声明、集结连接点。 通常通知与切入点关联在一起,一旦某连接点被触发,则会立即执行相应的通知。开发者借助于pointcut表达语言来完成pointcut的指定工作。25通知程序执行切入连接点AOP的术语的术语 通知通知(Advice)(Advice) 通知指切面(asp

17、ect)在特定连接点所执行的的动作。特定连接点由切入点(pointcut)指定。 主要的通知类型包括:Before、 AfterReturning、AfterThrowing、 After 、Around。 Before通知能够在特定连接点被触发前执行,如方法执行前执行的通知。其它类似。26AOP的术语的术语 引入(引入(introducionintroducion) 引入也称为inter-type声明(AspectJ5)。将新的接口、方法、成员变量动态引入到目标类、接口或切面中。 目标对象(目标对象(target Objecttarget Object) 被若干切面(aspect)装配过的对

18、象,也被称为被通知的对象。27AOP的术语的术语 织入(织入(weavingweaving) 将切面(Aspect)与目标对象组装在一起的过程称为织入。通过织入创建一个被通知的对象。 这些可以在编译时(例如使用AspectJ编译器),类加载时和运行时完成。28AOP的术语的术语 目标对象(目标对象(TargetObject) 被一个或者多个切面所通知的对象。也被称做被通知(advised)对象。 AOP代理(代理(AOPProxy) AOP框架创建的对象,用来实现切面契约(例如通知方法执行等等)。29AOP的术语的术语 切面切面(aspect)(aspect) 与OOP中对象的概念一样,是AO

19、P中的核心概念。 切面将切入点、通知、引入、目标对象等信息集结在一起,从而定义相应的织入规则,这样一个整体称为切面(aspect)。30通知通知AdviceSpring提供了5种通知(Advice)类型:Interception Around、Before、After Returning、Throw 和Introduction。它们分别在以下情况被调用: Interception Around Advice:在目标对象的方法执行前后被调用。 Before Advice:在目标对象的方法执行前被调用。 After Returning Advice:在目标对象的方法执行后被调用。 Throw Ad

20、vice:在目标对象的方法抛出异常时被调用。 Introduction Advice:一种特殊类型的拦截通知,只有在目标对象的方法调用完毕后执行。通知通知AdviceBefore Advice(前拦截规则类):public class BeforeInterceptor implements MethodBeforeAdvice public void before(Method arg0, Object arg1, Object arg2)throws Throwable System.out.println(before doing.); Arg0:业务逻辑方法。Arg1:执行业务逻辑方法

21、的参数。Arg2:调用业务逻辑方法的实例。通知通知AdviceAfter Advice(后拦截规则类):public class AfterInterceptor implements AfterReturningAdvice public void afterReturning(Object arg0, Method arg1, Object arg2 ) throws Throwable System.out.println( After returning. ); Arg0:业务逻辑方法。Arg1:执行业务逻辑方法的参数。Arg2:调用业务逻辑方法的实例。通知通知AdviceAround

22、 Advice(围绕拦截规则类):public class AroundInterceptor implements MethodInterceptor public Object invoke( MethodInvocation mi ) throws Throwable System.out.println( Begin. );Objectresult=ceed();System.out.println( finished! );return result;7.1.4通知通知AdviceBefore Advice会在目标对象的方法执行之前被呼叫。如同在便利店里,客户购买东西之前

23、,促销员要给他们一个热情的招呼。为了实现这一点,需要扩展MethodBeforeAdvice接口,该接口提供获取目标方法、参数及目标对象。public interface MethodBeforeAdvice void before(Method method, Object args, Object target) throws ThrowableIhello.java的代码如下:public interface Ihello public void hello(String name);HelloSpeaker.java的代码如下:public class HelloSpeaker imp

24、lements Ihello public void hello(String name) System.out.println(hello, +name); 7.1.4通知通知Advice在对HelloSpeaker不进行任何修改的情况下,想要在hello()方法执行之前,记录一些日志的服务,可以先实现MethodBeforeAdvice接口。LogBeforeAdvice.java的代码如下:import java.lang.reflect.Method;import java.util.logging.Level;import java.util.logging.Logger;impor

25、t org.springframework.aop.MethodBeforeAdvice;public class LogBeforeAdvice implements MethodBeforeAdviceprivate Logger logger=Logger.getLogger(this.getClass().getName();public void before(Mehod method,Object args,Object target) throws Throwablelogger.log(Levl.INFO, method starts+method);7.1.4通知通知Advi

26、ce在before()方法中,加入了一些记录日志的程序代码。applicationContext.xml的配置如下: Ihello logBeforeAdvice 7.1.4通知通知Advice写一个程序测试一下Before Advice的运作。SpringAOPDemo.java的代码如下:import org.springframework.context.ApplicationContext;import org.springframework.context.support.FileSystemXmlApplicationContext;public class SpringAOPDe

27、mo public static void main(String args) ApplicationContext context=new FileSystemXmlApplicationContext(/WebRoot/WEB-INF/ classes/applicationContext.xml); Ihello helloProxy=(Ihello)context.getBean(helloProxy); helloProxy.hello(Justin); 7.1.5切入点切入点PointcutIhello.java的代码如下:public interface Ihello publi

28、c void helloNewbie(String name); public void helloMaster(String name);HelloSpeaker类实现Ihello接口,代码如下:public class HelloSpeaker public void helloNewbie(String name) System.out.println(Hello, +name+newbie! ); public void helloMaster(String name) System.out.println(Hello, +name+master! ); 7.1.5切入点切入点Poin

29、tcutapplicationContext.xml的代码所示。在NameMatchMethodPointcutAdvisor的mappedName属性中,由于指定了“hello*”,所以当调用helloNewbie()或者helloMaster()方法时,由于方法名称的开头为“hello”,就会应用LogBeforeAdvice的服务逻辑,可以写程序来测试。SpringAOPDemo.java代码如下:import org.springframework.context.ApplicationContext;import org.springframework.context.support

30、.FileSystemXmlApplicationContext;public class SpringAOPDemo public static void main(String args) ApplicationContext context=new FileSystemXmlApplicationContext(/WebRoot/WEB-INF/ classes/ applicationContext.xml); Ihello helloProxy=(Ihello)context.getBean(helloProxy); helloProxy.helloNewbie(Justin); h

31、elloProxy.helloMaster(Tom); 7.1.6Spring对事务的支持对事务的支持在JDBC中,可以用Connection的setAutoCommit()方法,给定它false参数。在一连串的SQL语句后面,调用Connection的commit()来送出变更。如果中间发生错误,则调用rollback()来撤销所有的执行。try connection.setAutoCommit(false); /一连串SQL操作 mit();/执行成功,提交所有变更catch(SQLException e) connection.rollback();/发生错误,撤销所有变更7.1.6Sp

32、ring对事务的支持对事务的支持Spring提供编程式的事务管理(Programmatic transaction management)与声明式的事务管理(Declarative transaction management)。(1)编程式的事务管理。编程式的事务管理可以清楚地控制事务的边界,即自行实现事务何时开始、撤销、结束等,可以实现细粒度的事务控制。(2)声明式的事务管理。然而在多数情况下,事务并不需要细粒度的控制。采用声明式的事务管理,优点是Spring事务管理的相关API可以不用介入程序中,从对象的角度来看,并不知道它正被纳入事务管理中。7.1.6Spring对事务的支持对事务的支

33、持例如,可以在不修改UserDAO类的情况下,为这个类加入事务管理的服务。简化的方法是使用TransactionProxyFactoryBean,指定要介入的事务管理对象及其方法,这里需要修改配置文件。applicationContext.xml的代码所示。7.1.6Spring对事务的支持对事务的支持由于userDAO被userDAOProxy代理了,所以要做的是取得userDAOProxy,而不是userDAO。例如:SpringAOPDemo.javaimport org.springframework.context.ApplicationContext;import org.spri

34、ngframework.context.support.FileSystemXmlApplicationContext;public static void man(String args) ApplicationContext context=new FileSystemXmlApplicationContext(applicationContext.xml); User user=new User(); user.setName(Tome); user.setAge(new Integer(20); IUserDAO userDAO=(IUserDAO)context.getBean(us

35、erDAOProxy); userDAO.insert(user);7.2开开发发步步骤骤7.2.1为订单添加日志输出为订单添加日志输出1实现实现MethodBeforeAdvice接口接口在项目org.easybooks.bookstore.service.impl包下创建LogBeforeAdvice类。LogBeforeAdvice.java的代码如下:package org.easybooks.bookstore.service.impl;import java.lang.reflect.*;import java.util.logging.Level;import java.util

36、.logging.Logger;import org.springframework.aop.MethodBeforeAdvice;public class LogBeforeAdvice implements MethodBeforeAdviceprivate Logger logger=Logger.getLogger(this.getClass().getName();public void before(Method method,Object args,Object target) throws Exceptionlogger.log(Level.INFO, method start

37、s.+method);7.2.1为订单添加日志输出为订单添加日志输出2注册日志服务、配置代理注册日志服务、配置代理在applicationContext.xml中修改和配置所示。3输出订单日志输出订单日志部署运行网上书店程序,登录后选购几本图书,然后结账,成功下订单后,控制台会输出如下日志信息:一月 08, 2013 4:50:43 下午 org.easybooks.bookstore.service.impl.LogBeforeAdvice beforeINFO: method starts.public abstract org.easybooks.bookstore.vo.Orders

38、org.easybooks.bookstore.service. IOrderService.saveOrder(org.easybooks.bookstore.vo.Orders)输出效果如图7.3所示。7.2.1为订单添加日志输出为订单添加日志输出打开命令行,进入MySQL数据库,查询发现表orders中记录的订单信息与日志显示的完全一致,如图7.4所示。7.2.2将结账过程纳入事务管理将结账过程纳入事务管理如图7.5、图7.6所示,结账功能将购物车中的商品存入数据库,现在将为其增加声明式事务功能,将结账过程纳入Spring的事务管理中。7.2.2将结账过程纳入事务管理将结账过程纳入事务管

39、理7.2.2将结账过程纳入事务管理将结账过程纳入事务管理1增加事务管理器增加事务管理器修改applicationContext.xml,代码片段如下:PROPAGATION_REQUIRED7.2.2将结账过程纳入事务管理将结账过程纳入事务管理2修改修改applicationContext中的中的Service原来的代码如下:修改后,代码如下:7.2.2将结账过程纳入事务管理将结账过程纳入事务管理3知识点:知识点:bean继承简化继承简化xml配置配置使用bean继承来包含多重TransactionProxyFactoryBean声明的XML,开始于在上下文中定义一个TransactionProxyFactoryBean的abstract声明: 7.2.2将结账过程纳入事务管理将结账过程纳入事务管理下面创建bean,代码如下: 到目前为止,这个技术并没有节省更多的XML,但是考虑将要做的事情是让另一个bean事务化,只需要加一个abstractTxDefiniton的子Bean就可以了。 7.3知识点知识点Hibernate缓存、事务管缓存、事务管理理7.3.1缓存管理缓存管理1一级缓存一级缓存Session实现了一级缓存,它是事务级数据缓存。一旦事务结束,这个缓存也就失效。一个Session的生命周期对应一个数据库事务或

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论