Spring教程大全

上传人:夏** 文档编号:586329699 上传时间:2024-09-04 格式:PPT 页数:145 大小:301.50KB
返回 下载 相关 举报
Spring教程大全_第1页
第1页 / 共145页
Spring教程大全_第2页
第2页 / 共145页
Spring教程大全_第3页
第3页 / 共145页
Spring教程大全_第4页
第4页 / 共145页
Spring教程大全_第5页
第5页 / 共145页
点击查看更多>>
资源描述

《Spring教程大全》由会员分享,可在线阅读,更多相关《Spring教程大全(145页珍藏版)》请在金锄头文库上搜索。

1、SpringSpring教程大全教程大全目标理解什么是Spring理解Spring的用途Spring简介Spring是一个开源框架,它的目的是为了简化企业级系统开发而诞生的Spring从小里说,是个容器,往大里说,就是个框架Spring是轻量级的,它的Jar包只有1M多一点,而且,它是非侵入式的:你一般不需要在你的类里import它的包理解容器与框架什么是容器,请回忆ServletWebWeb容器容器容器容器Servlet AServlet B理解容器与框架什么是容器,请回忆ServletWebWeb容器容器容器容器Servlet AServlet AServlet BServlet A容器外

2、部的容器外部的Servlet 无法使用无法使用只有这个只有这个Servlet由容器管由容器管理,它才能被客户端调用,理,它才能被客户端调用,然后由容器负责实例化、然后由容器负责实例化、初始化、销毁这个初始化、销毁这个Servlet那么什么是框架WebWeb容器容器容器容器Servlet A客户端客户端每次请求和响应,都有些重复的事情要做,比如:国际化、日志、事务处理、异常处理、验证、自动处理请求参数等等那么什么是框架WebWeb容器容器容器容器Servlet A客户端客户端除此之外,应用程序里还需要经常访问一些服务,每种服务的访问方式、方法是不一样的消息服务DBWebServiceLDAPWe

3、bWeb容器容器容器容器Servlet ASpring框架框架这就是框架业务逻辑实现 A客户端客户端消息服务DBWebServiceLDAP日志事务处理异常处理国际化验证处理请求参数Framework的定义框架不仅要负责管理某些Bean的生命周期(容器的功能),还需要负责搭建某些基础设施(那些通用的部分)例如:Struts能够称之为一个框架,是因为它负责管理Action ActionForm ActionForward这些对象的生命周期;另外它提供了国际化、异常处理、自动包装表单请求、验证等通用的功能Hibernate也可以称之为一个框架,因为它维护持久化对象的生命周期,持久化对象的通用增删改

4、查方法Spring既是容器也是框架由Spring负责业务逻辑业务逻辑 A 对象的实例化、初始化、服务(被调用)等,这是Spring作为容器的职责Spring将大多数可重用、与业务逻辑无关的功能能够自行或交由其他组件完成、这是它作为一个框架的职责Spring与其它容器的不同Spring框架框架业务逻辑实现 A日志事务处理异常处理国际化验证处理请求参数业务逻辑类 A 是POJO,不需要实现特殊接口,也不需要继承基类。因此在容器外也是可用的Spring与其它框架的不同比如将Spring与我们刚学习的Struts框架,Hibernate框架相对比,他们的不同之处在于:Spring还可以集成其它框架,它

5、是一个“大”框架Spring是专注于企业应用的框架,它所涉及的领域非常之广泛Struts只是专注于实现Web应用程序开发的MVC部分Hibernate只是专注于数据持久层的部分WebWeb容器容器容器容器Servlet ASpring框架框架Spring可以集成Struts业务逻辑实现 A客户端客户端消息服务DBWebServiceLDAP日志事务处理异常处理Struts框架框架国际化验证处理请求参数WebWeb容器容器容器容器Servlet ASpring框架框架Spring可以集成Hibernate业务逻辑实现 A客户端客户端消息服务DBWebServiceLDAP日志事务处理异常处理St

6、ruts框架框架国际化验证处理请求参数Hibernat框架框架Hello,Spring创建Spring工程的步骤1.添加spring.jarcommons-logging.jarlog4j.jarlog4j.properties2.编写接口3.编写实现类1,实现类24.编写配置文件5.测试Log4j配置简介log4j.properties的位置log4j的日志级别:DEBUG,INFO,WARN,ERROR程序代码中指定日志信息的级别,根据配置文件,将不同级别的日志信息输出到文件或是控制台上Log4j配置简介log4j.rootLogger=WARN, CONSOLE, FILElog4j.a

7、ppender.CONSOLE =org.apache.log4j.ConsoleAppenderlog4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayoutlog4j.appender.CONSOLE.layout.ConversionPattern=%d %p %c - %m%nlog4j.appender.FILE=org.apache.log4j.FileAppenderlog4j.appender.FILE.File=file.loglog4j.appender.FILE.Append=falselog4j.appender

8、.FILE.layout=org.apache.log4j.PatternLayoutlog4j.appender.FILE.layout.ConversionPattern=%d %p %c - %m%n布局布局格式默认日志级别Appender负责指定输出位置Log4j配置简介log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppenderlog4j.appender.ROLLING_FILE.Threshold=ERROR log4j.appender.ROLLING_FILE.File=rolling.loglog4j.ap

9、pender.ROLLING_FILE.Append=truelog4j.appender.ROLLING_FILE.MaxFileSize=10KBlog4j.appender.ROLLING_FILE.MaxBackupIndex=1log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayoutlog4j.appender.ROLLING_FILE.layout.ConversionPattern=%d %p %c - %m%nlog4j.logger.org.springframework=INFOlog4j.logge

10、r.org.hibernate=INFOlog4j.logger.org.yihang=INFO针对某个包的日志级别设置针对某个Appender的日志级别设置Log4j使用注意事项Log4j在用在JBoss环境中使用方法需要注意:由于JBoss本身也使用了Log4j,因此为了避免冲突,你需要提供自己的log4j.properties和log4j.jarLog4j.properties需要放置在WEB-INF/classes目录下,与你的顶层包平级Log4j.jar需要放置在WEB-INF/lib下作业亚瑟王手下有一批圆桌骑士(knight),他们的接受亚瑟王的直接委派(order)。亚瑟王布置

11、给圆桌骑士的任务(task)有很多,比如:屠杀恶龙(kill dragon)、拯救美女(rescue beauty)等任务。每个任务都需要前期的准备工作(prepare)、执行(execute)、汇报几个步骤。另外,虽然圆桌骑士都都向亚瑟王宣誓忠诚、正直,但亚瑟王仍然不太放心。秘密派出间谍监视骑士们完成任务的过程,并要求间谍在任务完成时汇报(report)。请用面向对象的方法来描述上述需求第第 二二 章章 Spring IOC 什么是接口这个一个老问题,也是个新问题,取决你的认识抛开你以前对接口的理解,请记住一句话:考虑以下对象public class Person private Strin

12、g name;private int age;public void eat(String food) System.out.println(name + 正在吃 + food);public void sleep() System.out.println(name + 正在睡大觉);Person是一个普通是一个普通对象,不具有任何对象,不具有任何特征特征考虑以下接口public interface Salesman public void sell(String goods);public interface Housework public void doIt(String work);S

13、alesman是一个销售人员是一个销售人员接口,具有这个接口的接口,具有这个接口的类都会推销的技能类都会推销的技能Housework是一个家务人员是一个家务人员接口,具有这个接口的接口,具有这个接口的类都必须会做家务类都必须会做家务public class Person implements Housework, Salesman private String name;private int age;。public void doIt(String work) System.out.println(name + 正在做 + work);public void sell(String good

14、s) System.out.println(name + 正在销售 + goods);当一个类实现了一个接口,那么当一个类实现了一个接口,那么它就具有了一种新的身份它就具有了一种新的身份如果它实行了多个接口,它如果它实行了多个接口,它就具有了多重身份就具有了多重身份那么实现接口的意义是?在商店,就(可以)把你当做销售人员用在家,就(可以)把你当劳力用举一些实际的例子现在person1和person2都可以胜任销售人员用,但是只有一个职位,商场可以先雇佣一个销售人员,以后遇到好的再换。SalesmanPerson1Person2商场商场商场商场人才市场人才市场人才市场人才市场不好的选择如果变成商

15、场招聘的不是一个“职位”,而是一个具体的人(可以想象商场老板任人唯亲),那么即使人才市场有更优秀的李四、王五,那么替换掉张三是很难的张三张三李四李四商场商场商场商场人才市场人才市场人才市场人才市场王五王五 它们不是老板它们不是老板的亲戚的亲戚用在实际设计中业务逻辑接口业务逻辑接口实现类实现类A实现类实现类BActionAction业务实现包业务实现包业务实现包业务实现包但还有一点没有考虑到由谁去筛选人才?SalesmanPerson1Person2商场商场商场商场人才市场人才市场人才市场人才市场商场商场商场商场市场部市场部人事部人事部SalesmanPerson2人才市场人才市场人才市场人才市

16、场Person1Person2选拔选拔任命任命这里人事部的职责就是负责产生销售人员再次提醒大家,不是产生具体对象,而是产生一个身份(某种职务)在编程技术里,称人事部为:对象工厂在Spring里,就对应着各种BeanFactory什么是IoCIoC即控制反转,有时候也叫做DI(依赖注入)举报纸的例子举商场的例子考虑下列情形是自己到报摊买报纸好还是在邮局订阅,让人给送来好?考虑下列情形商场的例子里,是老板亲自去选拔、任命销售人员还是老板下一个命令,让手下的人把这件事办妥了?对于下面的例子public class HelloImpl4 implements Hello private Message

17、 msg;public Message getMsg() return msg;public void setMsg(Message msg) this.msg = msg;public String sayHello(String name) return this.msg.getMsg() + + name;HelloImpl4这个类需要这个类需要用到用到Message类类那么,那么,是由是由HelloImpl4自己自己实例化实例化Message类呢类呢还是最好有人把还是最好有人把Message类实例化类实例化好了,给它送过来呢好了,给它送过来呢实现注入的步骤A.在配置文件中声明好要注入的

18、类要注入的类定义要注入的类定义B.选择注入的方式常用的注入的方式有两种构造方法注入Setter方法注入对于构造注入public class HelloImpl4 implements Hello private Message msg;public HelloImpl4(Message msg) this.msg = msg;被注入的属性被注入的属性由由Spring注入注入对于Setter方法注入public class HelloImpl4 implements Hello private Message msg;public void setMsg(Message msg) this.ms

19、g = msg; 被注入的属性被注入的属性由由Spring注入注入C.使用被注入的类BeanFactory factory = new XmlBeanFactory(resource);Hello hello = (Hello) factory.getBean(hello4);hello.sayHello(Spring);public String sayHello(String name) return this.msg.getMsg() + + name;msg属性的值在使用前已经在getBean()的过程中被注入好了举例演示spring中如何使用hibernate的session fac

20、tory请同学回答,在这个例子里,谁依赖于谁,谁被注入了?还要注意通过这个例子,掌握属性类型为Properties和数组时怎么注入开拓思路 业务实现类业务实现类业务接口业务接口使用者使用者数据访问类数据访问类A数据访问类数据访问类B数据访问类数据访问类C开拓思路 业务实现类业务实现类数据访问类数据访问类A数据访问类数据访问类B数据访问类数据访问类C业务接口业务接口使用者使用者业务接口业务接口数据访问类数据访问类A数据访问类数据访问类B数据访问类数据访问类C给业务实现类给业务实现类添加属性添加属性给使用者类给使用者类添加属性添加属性开拓思路 业务实现类业务实现类数据访问类数据访问类A数据访问类数

21、据访问类B数据访问类数据访问类C业务接口业务接口使用者使用者业务接口业务接口数据访问类数据访问类A数据访问类数据访问类B数据访问类数据访问类C由由Spring注入注入这些属性这些属性由由Spring注入注入这些属性这些属性其他可以把所有的Bean理解为Matrix这个虚拟世界的生活着的人(相信都看过黑客帝国),他们并不知道自己的真实身份,也不知道真实世界(Spring)的存在如果想知道自己是谁,需要实现BeanNameAware接口,有了这个接口,这个Bean就成为了崔妮绨、墨非司那种身份的人如果想去创造这个世界,需要实现BeanFactoryAware接口,有了这个接口,这个Bean就可以成

22、为neo(尼奥)救世主作业使用Spring的BeanFactory和配置文件改写网上银行项目第第 三三 章章 Spring AOP 什么是AOP为了理解AOP,请思考如下需求:角色:上帝,人(每个人都有大脑)现在上帝希望知道每个人的想法,请用面向对象的方法解决设计登场角色上帝,只有一个public class God /* * 上帝的读心术 * param mind 某个人的思想 */public void read(String mind) log.debug(上帝知道了,某个人正在想:“ + mind + ”);设计登场角色人,好几十亿public class Person private

23、 Brain brain;public void look(String thing) if(thing.equals(美女)log.debug(this.brain.thinking(上帝真伟大,造出来这么漂亮的人); else if (thing.equals(丑八怪) log.debug(this.brain.thinking(上帝真XX.); else log.debug(this.brain.thinking();设计登场角色大脑,重要器官,每个人有自己的大脑public class Brain public String thinking(String thing)if(thing

24、 = null | thing.trim().length() = 0) return (发呆中.); else return (正在思考“ + thing + ”的问题);解决问题为了要知道人们的思想,上帝决定用换脑的手段来达到目的由于人在出生时并不知道自己的大脑是怎么来的(由Spring注入的),因此,可以在他出生时安装另一个大脑换脑的两种方法用继承方式用接口方式使用继承的方式public class BrainExt extends Brain private God god;public void setGod(God god) this.god = god;Overridepubli

25、c String thinking(String thing) / 告诉上帝god.read(thing);return super.think(thing);使用接口的方式实际上,只要能“思考”,人类不在意究竟给他的脑袋里装一个大脑还是一个石头(假如石头能思考的话)“大脑”只是一种能够思考的象征因此,重新审视我们的设计,将大脑变成接口,变成一个抽象的概念使用接口的方式public class BrainProxy implements Brainprivate God god;private Brain brainNatural;public void setBrainNatural(Bra

26、in brainNatural) this.brainNatural = brainNatural;public String thinking(String thing) god.read(thing);return brainNatural.thinking(thing);public void setGod(God god) this.god = god;优先选择接口而非继承当需要进行动态代理时,接口比继承更容易实现接口具有更好的扩展性问题上帝不想创建过多的代理对象,仅仅希望实现具体操作使用Spring提供的办法刚才的例子里,无论是使用继承还是接口进行换脑,在设计模式里都称为代理模式请大

27、家区分代理与被代理对象分别是谁Spring为代理提供了更方便的控制正常操作正常操作Spring中AOPAOP即面向切面的编程在AOP的概念中,将刚才的场景中的角色划分的更为细致切面里执行切面里执行附加操作附加操作Pointcut正常操作之前正常操作之前正常操作之前正常操作之前正常操作之后正常操作之后正常操作之后正常操作之后上例中的上帝,称之为Advice(被通知对象),它知道该做什么关于上帝何时在什么时间、地点被通知,称之为Pointcut(切入点)对于真实的大脑,称之为Target(目标对象)对于假的大脑,不管是真实大脑的子类还是它们实现了共同的接口,都称之为Proxy(代理对象)Sprin

28、g中的Advice和Pointcut常见的Advice和Pointcut的类型MethodBeforeAdviceAfterReturningAdviceThrowsAdviceMethodInterceptor配置文件相应的改动god public class God implements MethodBeforeAdvicepublic void read(String mind) System.out.println(上帝知道了,某个人正在想:“ + mind + ”);public void before(Method method, Object args, Object targe

29、t)throws Throwable read(args0.toString();在方法执行前通知在方法执行前通知告知你执行的方法、方法的参数告知你执行的方法、方法的参数s还有目标(被代理的)对象还有目标(被代理的)对象注意事项Advice仅用于通知,如果需要拦截方法的调用需要使用Interceptor无论是MethodBeforeAdvice、AfterReturningAdvice、ThrowsAdvice它们都不能改变方法的执行(本身的行为)而Interceptor具有改变方法行为的能力MethodInterceptor需要实现的方法注意,一旦实现了MethodInterceptor,那

30、些Advice(通知)就不管用了public Object invoke(MethodInvocation mi) throws Throwable if(mi.getArguments()0.toString().indexOf(XX) 0)return (凡人,别做无谓的思考了.);/throw new RuntimeException(现在大脑一片混乱,无法思考); else return mi.proceed();改变方法的行为,改变方法的行为,只在一念之间只在一念之间Proceed让方法让方法继续执行继续执行讨论使用Spring提供的ProxyFactoryBean提供代理的好处不必

31、自己创建整个代理对象了,代理对象由ProxyFactoryBean产生,程序员只需要关注实现具体功能使用ProxyFactoryBean可以创建几乎任何对象的代理,减少了程序中代理类的数量问题但是现在上帝很郁闷,现在它必须戴上一大堆身份,弄得身上脏兮兮的现在的结果是使得上帝依赖于Spring提供的接口,上帝离了Spring就活不了了怎么办Spring2.0里的AOP使用AspectJ使用AspectJ达到相同的效果在AspectJ的表达中上帝是一个POJO,不需要实现特定的接口就可进行AOP操作这个例子里,上帝在AspectJ中被成为Aspect(即切面),它的目的是执行正常逻辑之外的附加操作

32、与之前的Spring1.x中的AOP相比,可以把Advisor(通知)看作是知道了切入地点的Aspect使用AspectAOP的步骤1.将BeanFactory换成ApplicationContextApplicationContext是BeanFactory的子接口ApplicationContext提供了更多的功能如果将BeanFactory比作一个小作坊,那么ApplicationContext就是一个生产车间使用AspectAOP的步骤2.使用spring2.0中提供的schema样式的配置文件God类的变化public class God private static Log log

33、 = LogFactory.getLog(God.class);/* * 上帝的读心术上帝的读心术 * param mind 某个人的思想某个人的思想 */public void read(String thing) log.debug(上帝知道了,某个人正在想:上帝知道了,某个人正在想:“ + thing + ”);God不需要再实现不需要再实现那些那些Advice接口接口配置文件的变化 它们如何对应public class God public void read(String thing) log.debug(上帝知道了,某个人正在想:上帝知道了,某个人正在想:“ + thing + ”

34、); package org.yihang.aop;public interface Brain public String thinking(String thing);其他类型的JoinPoint - 表示已经定义好连接点的切面Pointcut表达式execution表示执行public表示公共方法第一个*表示任意返回类型第二个*表示任意方法名(.)表示任意参数execution(public * *(.) 更多的例子execution(* set*(.)execution(* transfer()execution(* transfer(*)execution(* transfer(*,

35、String)execution(* com.xyz.service.AccountService.*(.) execution(* com.xyz.service.*.*(.) execution(* com.xyz.service.*.*(.) 问题如何配合切入点表达式,向切面类传递参数使用新语法的好处减少了代理类在切入点的控制上更为细腻第第 四四 章章 Spring AOP 的应用的应用回顾AOP的目的即在正常的业务操作之外增加的附加操作通过切入点(pointcut)指名进行哪些切面(aspect)操作ProxyFactoryBeaninterceptorNamestargetNamep

36、roxyInterfaces拦截器(Interceptor),通知(Advice),和切面的不同(Aspect)AOP的应用事务切面日志切面其它附加操作切面事务切面在介绍事务切面之前,回顾网上银行的项目,并使用Spring IOC注入业务实现类所需的sessionFactory实现步骤和问题思考:实现业务接口业务接口和业务实现类业务实现类(AccountService、LogService)sessionFactory如何注入的,应该注入给谁?事务由谁来管理?优化现在项目经理提出需求,希望改进代码的结构,达到如下目标:transfer方法(或其它业务方法)在执行时,事务自动开始在正确完成后,事

37、务提交,并且关闭hibernate session在出现RuntimeException(或其子类)异常时,事务回滚,并关闭hibernate session其他异常,仍执行提交关闭的操作Spring的解决方案方案A:使用事务拦截器并代理业务实现类方案B:使用事务advice 和aspect 切面来实现事务拦截方案A第一步,改写AccountService业务实现类第二步,定义ProxyFactoryBean以返回AccountService代理对象proxyInterfacestargetNameinterceptorNames 这里添加事务拦截器事务拦截器第三步定义事务拦截器PROPAGA

38、TION_REQUIREDPROPAGATION_REQUIRES_NEW事务属性以及事务属性以及事务管理器事务管理器Show Time修改log4j.properties,以便观察Spring执行过程log4j.logger.org.springframework.aop=debuglog4j.logger.org.springframework.transaction=debuglog4j.logger.org.springframework.orm.hibernate3=debug事务管理器Spring由于需要为多种数据层的实现提供集成支持,针对不同的情况,定义了各种事务管理器,一定要选

39、择正确的事务管理器比如:DataSourceTransactionManager 对应JDBC事务HibernateTransactionManager 对应Hibernate提供的事务JtaTransactionManager 对应JTA事务大多数事务管理器都需要设置dataSource(数据源)属性,对于HibernateTransactionManager可以只设置sessionFactory属性事务属性常见的事务属性有:事务的传播行为事务的隔离级别事务是否只读 针对只读事务,Spring在某些情况下会提供优化事务的传播行为以下的定义可以在TransactionDefinition中找到

40、PROPAGATION_REQUIREDPROPAGATION_SUPPORTSPROPAGATION_MANDATORYPROPAGATION_REQUIRES_NEWPROPAGATION_NOT_SUPPORTEDPROPAGATION_NEVER事务的传播行为PROPAGATION_REQUIRED表示如果没有事务,则开始新的事务,事务已经存在,则加入当前事务PROPAGATION_SUPPORTS 表示如果事务已经存在,则加入当前事务,如果没有事务,不会开始新事务PROPAGATION_MANDATORY 表示必须有事务存在,并加入当前事务,否则抛出异常PROPAGATION_REQ

41、UIRES_NEW 表示每次都开始一个全新事务PROPAGATION_NOT_SUPPORTED 表示不会开始或加入事务PROPAGATION_NEVER 表示不会开始或加入事务,如果事务已存在,抛出异常事务的隔离级别以下的定义可以在TransactionDefinition中找到ISOLATION_READ_UNCOMMITTEDISOLATION_READ_COMMITTEDISOLATION_REPEATABLE_READISOLATION_SERIALIZABLE事务的隔离级别首先明确隔离级别指的都是同一个事务中ISOLATION_READ_UNCOMMITTED表示会读取到未提交的数

42、据ISOLATION_READ_COMMITTED表示读取到的是已经提交的数据ISOLATION_REPEATABLE_READ表示多次读取的数据是相同的ISOLATION_SERIALIZABLE表示就好像没有别的用户在修改数据库中的数据一样如何使用隔离级别对于大多数数据库来说,事务的隔离级别是ISOLATION_READ_COMMITTED,我们不需要做更多的设置,就可以很好的工作了将事务的隔离级别设置为ISOLATION_REPEATABLE_READ可以防止丢失更新,但这样做会严重影响系统的并发性,因此更多地是采用乐观锁的形式ISOLATION_SERIALIZABLE并非你想象中的锁

43、定一切!继续完成需求第四步,完成LogService业务实现类及其代理对象的定义,修改事务拦截器第五步,定义一个Advice实现ThrowsAdvice和MethodBeforeAdvice 以便处理日志和其它附加逻辑第六步,将此Advice 添加至合适的位置流程分析当事务拦截器中的设置如下时PROPAGATION_REQUIREDPROPAGATION_REQUIRES_NEW执行顺序1.执行AccountService代理的transfer方法2.检查此代理定义的所有拦截器(有事务拦截器,和一个Advice)3.根据transfer方法事务的传播规则(REQUIRED),开启一个新的事务T

44、x_A,打开Session_A4.因为Advice实现了MethodBeforeAdvice接口,因此首先执行Advice中的before方法5.Before方法中,使用了LogService代理的log方法6.检查LogService代理定义的拦截器(有事务拦截器)7.根据log方法的传播规则(REQUIRES_NEW),又开启一个新的事务Tx_B,打开Session_B8.执行log方法9.当log方法成功执行,Tx_B提交,Session_B关闭10.执行transfer方法11.当transfer方法成功执行,Tx_A提交,Session_A关闭当transfer发生异常1.执行Acc

45、ountService代理的transfer方法2.检查此代理定义的所有拦截器(有事务拦截器,和一个Advice)3.根据transfer方法事务的传播规则(REQUIRED),开启一个新的事务Tx_A,打开Session_A4.因为Advice实现了MethodBeforeAdvice接口,因此首先执行Advice中的before方法5.Before方法中,使用了LogService代理的log方法6.检查LogService代理定义的拦截器(有事务拦截器)7.根据log方法的传播规则(REQUIRES_NEW),又开启一个新的事务Tx_B,打开Session_B8.执行log方法9.当lo

46、g方法成功执行,Tx_B提交,Session_B关闭10.执行transfer方法11.当transfer方法抛出异常,执行Advice 的afterThrowing 方法12.Tx_A回滚,Session_A关闭流程分析当事务拦截器中的设置如下时PROPAGATION_REQUIREDPROPAGATION_REQUIRED执行顺序1.执行AccountService代理的transfer方法2.检查此代理定义的所有拦截器(有事务拦截器,和一个Advice)3.根据transfer方法事务的传播规则(REQUIRED),开启一个新的事务Tx_A,打开Session_A4.因为Advice实现

47、了MethodBeforeAdvice接口,因此首先执行Advice中的before方法5.Before方法中,使用了LogService代理的log方法6.检查LogService代理定义的拦截器(有事务拦截器)7.根据log方法的传播规则( REQUIRED ),加入当前的事务Tx_A8.执行log方法9.执行transfer方法10.当transfer方法成功执行,Tx_A提交,Session_A关闭当transfer发生异常1.执行AccountService代理的transfer方法2.检查此代理定义的所有拦截器(有事务拦截器,和一个Advice)3.根据transfer方法事务的传

48、播规则(REQUIRED),开启一个新的事务Tx_A,打开Session_A4.因为Advice实现了MethodBeforeAdvice接口,因此首先执行Advice中的before方法5.Before方法中,使用了LogService代理的log方法6.检查LogService代理定义的拦截器(有事务拦截器)7.根据log方法的传播规则( REQUIRED ),加入当前的事务Tx_A8.执行log方法9.执行transfer方法10.当transfer方法抛出异常,执行Advice 的afterThrowing 方法11.Tx_A回滚,Session_A关闭方案B用Spring 2.0的新

49、语法可以使用新的来替换事务拦截器使用减少配置中代理类的数量第第 五五 章章 Spring Template技术技术回顾事务切面日志切面其它附加操作切面什么是模板回忆使用JSP进行开发的过程先使用开发好静态的HTML页面,然后使用JSP标签替换会变化的内容这里的关键是抽象出其中动态的、变化的内容JSP实际就是一种模板语言Java类中的模板在类的开发中,也可以使用类似的技术:将重复的代码视为代码模板,使用变化的代码去填充模板领会模板技术,是Java编程人员登堂入室(由普通程序员架构师)的第一步示例第一步,审查现有代码,抽取出不同的部分(可以使用extract method),保留相似的部分第二步,

50、将相似代码抽取为模板类(extract class)第三步,这时候肯定有一处的调用方式不同,将其抽象为接口,注意接口的返回值、异常、参数第四步,使用模板类替换原有实现第五步,将原本抽取出的方法填充模板模板和代理在设计模式里,模板模式和代理模式有些类似主要的区别是,代理的目的是实现正常逻辑之外的附加逻辑,甚至会改变原有操作的行为而模板是规定了你必须执行的部分,那些每次执行行为不同的部分需要程序员自己实现模板的例子:Struts中的Action中的execute方法,Servlet中的doGet、doPost方法模板和代理都是设计框架必不可少的知识Spring中的模板技术HibernateTemp

51、lateJdbcTemplate HibernateTemplateHibernateTemplate里那些静态(必须执行)的部分获取session判断当前的方法是否处在一个事务中异常处理部分:处理异常Finally块:看看是否应当关闭session这些功能已经由Spring提供好了动态部分动态部分需要我们自己实现:public interface HibernateCallback Object doInHibernate(Session session) throws HibernateException, SQLException;演示HibernateTemplate的使用小结其实 H

52、ibernateTemplate在Spring集成早些版本的hibernate(2.x)时是非常有用的,它将session与当前线程进行绑定,确保了进行多次方法调用后事务的提交回滚和session的关闭都是针对同一个session目前的Hibernate(3.x)中的sessionFactory.getCurrentSession();提供了相同的功能,因此template的功能有所重复,你可以根据自己情况选择使用请对比WebBank工程中的HibernateAccountServiceNew HibernateAccountServiceTx两个类来理解它们的异同JDBCTemplate使用

53、JDBC与Hibernate模板的不同之处:JDBC模板的使用依赖于javax.sql.DataSource,而Hibernate模板的使用依赖于org.hibernate.SessionFactory相同之处:它们都会应用事务切面,自动处理事务的提交和回滚无须自己打开关闭Session或ConnectionJavax.sql.DataSource我们以前介绍过,DataSource一般是由应用服务器提供的,用于获取数据库连接的连接工厂它同时集成了连接池的功能为了便于不依赖于容器,方便在容器外部进行测试,Spring提供了一个实现了DataSource接口的类DriverManagerData

54、Source,它仅仅是对数据库直连方式的一个简单封装,不提供连接池的功能事务管理器为了配合JDBC的事务管理,需要将事务管理器的实现换为DataSourceTransactionManager演示JDBCTemplate的使用三层结构之DAO什么是DAODAO即Data Access Object,在hibernate等持久层框架出现之前,DAO用于解耦业务逻辑与底层的数据访问之间的联系(能够方便的在不同的数据库切换)DAO也是通过DAO接口DAO实现类来完成解耦操作的如果已经使用了一种持久层框架,那么DAO基本上是多余的DAO举例例如在我们现有的设计里,JDBCLogService和JDBC

55、AccountService这两个实现类都会访问数据库在业务逻辑代码之外,存在很多与之无关的数据访问代码并且,如果现在访问的其它类型的数据库,那么SQL语句会有差异因此,将这些数据访问功能独立于业务逻辑之外,是一种好的解决方案实现思路业务逻辑实现类中不需要知道如DataSource对象,也无须实现findAccount、insertTransferRecord、updateAccount等方法,它只需要知道一个或几个DAO接口接口即可DAO实现实现负责以上方法的实现,跟数据源对象打交道,如果需要使用不同的数据库,那么分别实现相应的DAO实现类实现类业务逻辑实现类中声明一个类型为DAO接接口口的

56、属性,由Spring依赖注入DAO实现实现作业使用DAO+JDBC来修改课堂示例第第 六六 章章 Spring 与表现层集成与表现层集成回顾Spring是如何集成业务逻辑层的?通过接口实现类的方式解耦业务层与其它层,主要是用到了控制反转(依赖注入)的办法通过AOP的方法,分离事务、日志等切面操作,让业务逻辑更为清晰Spring是如何集成持久层的?通过模板技术,让具体的持久层实现无须考虑如何获得连接,关闭连接(或指session)等繁琐操作,使程序员专心处理数据CURD操作如果使用了hibernate等持久层框架,DAO就不重要了表现层集成Spring可以与多种表现层技术实现集成,其实与表现层集

57、成以我的理解就是业务逻辑业务逻辑如何被调用如何被调用的问题,可以分以下几个方面与某种Web框架相集成,如Struts,DWR等与某种java桌面应用程序相集成,如Swing来调用业务逻辑与某种其它语言的应用程序集成,如.net的程序与Struts集成Spring与Struts集成有两种方式:A.使用Struts调用Spring。优点是直接了当,容易理解,缺点是无法使用Spring的依赖注入B.使用Spring来管理Struts中的Action。优点是可以为Action注入业务逻辑实现与Struts集成方法A. 使用Struts调用Spring步骤:1.添加Spring提供的 ContextLo

58、aderListener和contextConfigLocation属性以指明Spring配置文件的位置,其原理是使用了Listener Servlet在Web工程加载的时候载入了ApplicationContext,并将其放入Servlet Context中2.使用Spring提供的 WebApplicationContextUtils从ServletContext中获取 ApplicationContext3.利用ApplicationContext获取业务逻辑Bean4.使用业务逻辑Bean与Struts集成如果认为以上步骤3中的方式不够简便,可以选择将你的Action继承自Spring

59、提供的 XXXActionSupport 基类与Struts集成方法B. 使用Spring来管理Struts中的Action步骤:1.添加Spring提供的 ContextLoaderListener和contextConfigLocation属性2.为所有Action添加类型为业务逻辑接口的属性和相应的Set方法,为注入做准备与Struts集成3.为struts-config.xml添加一个插件管理Struts Actions的配置文件管理原有Beans的配置文件与Struts集成4.配置针对struts action的配置文件,默认路径放在WEB-INF下,默认名称为action-serv

60、let.xmlbean 需要配置name属性,值为Action的路径和以前一样的方式注入业务逻辑bean与Struts集成5.为struts-config.xml配置,注意也可以选择第六步的方式与Struts集成6.将struts-config.xml中所有所有action的定义进行修改,注意也可以选择第五步的方式替换与Struts集成最终简化办法,在方法B.的第2步后,在struts-config.xml中添加:使用spring 2.0中的新特性,自动“织入”Action所需的业务逻辑Bean默认方式是根据业务逻辑Bean的类型织入的小结Spring和Struts的集成方式就是这些了,没有想

61、象中的复杂,严格按照步骤做一定不会错但话说回来,集成web应用程序中的难点不在于此,而是在于事务及事务及Session的管理的管理SSH中结合难点事务何时开始,何时结束Session何时打开,何时关闭典型的两种做法A.一个request对应多个事务,每个事务用到一个session,也就是我们现在的做法B.一个request对应多个事务,但只用到一个session,这种做法在以前的课程里也讲过,叫做session per request模式,也可以称之为Open Session In ViewA. 做法的流程分析客户端发送请求,经过Action来调用业务逻辑方法A与业务逻辑方法B方法A开启Ses

62、sion_A,开始事务A,执行之(中间若有拦截器、Advice等,则根据事务属性可能开启新的事务和连接,下同)方法A执行成功,事务A提交,Session_A关闭方法B开启Session_B,开始事务B,执行之方法B执行成功,事务B提交,Session_B关闭最后返回响应B. 做法的流程分析客户端发送请求,经过Action来调用业务逻辑方法A与业务逻辑方法B开启Session_A,方法A开始事务A,执行之(中间若有拦截器、Advice等,则根据事务属性可能开启新的事务或加入当前事务,下同)方法A执行成功,事务A提交方法B开始事务B,执行之方法B执行成功,事务B提交返回响应最后Session_A关

63、闭B.做法的优势B. 做法的优势在于有效地利用了Hibernate的一级缓存(因为没有重复打开关闭Session)但B. 的做法仅能在持久层使用 Hibernate或JPA(另外一种几乎和Hibernate完全一样的持久层技术)的情况下使用Spring如何实现做法B.一种做法是使用Spring提供的filter,其原理是使用过滤器Servlet在请求来时打开Session,在响应后关闭SessionOpenSessionInViewFilterorg.springframework.orm.hibernate3.support.OpenSessionInViewFilterOpenSessionInViewFilter*.do与DWR整合相当简单,整合仅仅涉及到远程Bean的生成方式,原来是每次new一个,现在是使用Spring的Bean工厂产生注意它的去向结束结束

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 建筑/环境 > 施工组织

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号