版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第 一 章,Spring 简介,目标,理解什么是Spring 理解Spring的用途,Spring简介,Spring是一个开源框架,它的目的是为了简化企业级系统开发而诞生的 Spring从小里说,是个容器,往大里说,就是个框架 Spring是轻量级的,它的Jar包只有1M多一点,而且,它是非侵入式的:你一般不需要在你的类里import它的包,理解容器与框架,什么是容器,请回忆Servlet,Web容器,Servlet A,Servlet B,理解容器与框架,什么是容器,请回忆Servlet,Web容器,Servlet A,Servlet B,Servlet A,容器外部的Servlet 无法使
2、用,只有这个Servlet由容器管理,它才能被客户端调用,然后由容器负责实例化、初始化、销毁这个Servlet,那么什么是框架,Web容器,Servlet A,客户端,每次请求和响应,都有些重复的事情要做,比如:国际化、日志、事务处理、异常处理、验证、自动处理请求参数等等,那么什么是框架,Web容器,Servlet A,客户端,除此之外,应用程序里还需要经常访问一些服务,每种服务的访问方式、方法是不一样的,消息服务,DB,Web Service,LDAP,Web容器,Servlet A,Spring框架,这就是框架,业务逻辑实现 A,客户端,消息服务,DB,Web Service,LDAP,F
3、ramework的定义,框架不仅要负责管理某些Bean的生命周期(容器的功能),还需要负责搭建某些基础设施(那些通用的部分) 例如:Struts能够称之为一个框架,是因为它负责管理Action ActionForm ActionForward这些对象的生命周期;另外它提供了国际化、异常处理、自动包装表单请求、验证等通用的功能 Hibernate也可以称之为一个框架,因为它维护持久化对象的生命周期,持久化对象的通用增删改查方法,Spring既是容器也是框架,由Spring负责业务逻辑 A 对象的实例化、初始化、服务(被调用)等,这是Spring作为容器的职责 Spring将大多数可重用、与业务逻
4、辑无关的功能能够自行或交由其他组件完成、这是它作为一个框架的职责,Spring与其它容器的不同,Spring框架,业务逻辑实现 A,业务逻辑类 A 是POJO,不需要实现特殊接口,也不需要继承基类。因此在容器外也是可用的,Spring与其它框架的不同,比如将Spring与我们刚学习的Struts框架,Hibernate框架相对比,他们的不同之处在于: Spring还可以集成其它框架,它是一个“大”框架 Spring是专注于企业应用的框架,它所涉及的领域非常之广泛 Struts只是专注于实现Web应用程序开发的MVC部分 Hibernate只是专注于数据持久层的部分,Web容器,Servlet
5、A,Spring框架,Spring可以集成Struts,业务逻辑实现 A,客户端,消息服务,DB,Web Service,LDAP,日志,事务处理,异常处理,Struts框架,Web容器,Servlet A,Spring框架,Spring可以集成Hibernate,业务逻辑实现 A,客户端,消息服务,DB,Web Service,LDAP,日志,事务处理,异常处理,Struts框架,Hibernat框架,Hello,Spring,创建Spring工程的步骤 添加perties 编写接口 编写实现类1,
6、实现类2 编写配置文件 测试,Log4j配置简介,perties的位置 log4j的日志级别:DEBUG,INFO,WARN,ERROR 程序代码中指定日志信息的级别,根据配置文件,将不同级别的日志信息输出到文件或是控制台上,Log4j配置简介,log4j.rootLogger=WARN, CONSOLE, FILE log4j.appender.CONSOLE =org.apache.log4j.ConsoleAppender log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout log4j.appende
7、r.CONSOLE.layout.ConversionPattern=%d %p %c - %m%n log4j.appender.FILE=org.apache.log4j.FileAppenderlog4j.appender.FILE.File=file.loglog4j.appender.FILE.Append=falselog4j.appender.FILE.layout=org.apache.log4j.PatternLayoutlog4j.appender.FILE.layout.ConversionPattern=%d %p %c - %m%n,布局,布局格式,默认日志级别,Ap
8、pender 负责指定输出位置,Log4j配置简介,log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppenderlog4j.appender.ROLLING_FILE.Threshold=ERROR log4j.appender.ROLLING_FILE.File=rolling.log log4j.appender.ROLLING_FILE.Append=true log4j.appender.ROLLING_FILE.MaxFileSize=10KB log4j.appender.ROLLING_FILE.MaxBacku
9、pIndex=1 log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout log4j.appender.ROLLING_FILE.layout.ConversionPattern=%d %p %c - %m%n .springframework=INFO.hibernate=INFO.yihang=INFO,针对某个包的日志级别设置,针对某个 Appender的日志级别设置,Log4j使用注意事项,Log4j在用在JBoss
10、环境中使用方法需要注意:由于JBoss本身也使用了Log4j,因此为了避免冲突,你需要提供自己的perties和log4j.jar Lperties需要放置在WEB-INF/classes目录下,与你的顶层包平级 Log4j.jar需要放置在WEB-INF/lib下,作业,亚瑟王手下有一批圆桌骑士(knight),他们的接受亚瑟王的直接委派(order)。亚瑟王布置给圆桌骑士的任务(task)有很多,比如:屠杀恶龙(kill dragon)、拯救美女(rescue beauty)等任务。每个任务都需要前期的准备工作(prepare)、执行(execute)、汇
11、报几个步骤。另外,虽然圆桌骑士都都向亚瑟王宣誓忠诚、正直,但亚瑟王仍然不太放心。秘密派出间谍监视骑士们完成任务的过程,并要求间谍在任务完成时汇报(report)。 请用面向对象的方法来描述上述需求,第 二 章,Spring IOC,什么是接口,这个一个老问题,也是个新问题,取决你的认识 抛开你以前对接口的理解,请记住一句话:,接口是一种身份的象征,考虑以下对象,public class Person private String name; private int age; public void eat(String food) System.out.println(name + 正在吃 +
12、 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); ,Salesman是一个销售人员 接口,具有这个接口的 类都会推销的技能,Housework是一个家务人员 接口,具有这个接口的 类都必须会做家务,public class Pe
13、rson implements Housework, Salesman private String name; private int age; 。 public void doIt(String work) System.out.println(name + 正在做 + work); public void sell(String goods) System.out.println(name + 正在销售 + goods); ,当一个类实现了一个接口,那么 它就具有了一种新的身份 如果它实行了多个接口,它 就具有了多重身份,那么实现接口的意义是?,在商店,就(可以)把你当做销售人员用 在家
14、,就(可以)把你当劳力用,举一些实际的例子,现在person1和person2都可以胜任销售人员用,但是只有一个职位,商场可以先雇佣一个销售人员,以后遇到好的再换。,Salesman,Person1,Person2,商场,人才市场,不好的选择,如果变成商场招聘的不是一个“职位”,而是一个具体的人(可以想象商场老板任人唯亲),那么即使人才市场有更优秀的李四、王五,那么替换掉张三是很难的,张三,李四,商场,人才市场,王五,它们不是老板 的亲戚,用在实际设计中,业务逻辑接口,实现类A,实现类B,Action,业务实现包,但还有一点没有考虑到,由谁去筛选人才?,Salesman,Person1,Per
15、son2,商场,人才市场,商场,市场部,人事部,Salesman,Person2,人才市场,Person1,Person2,选拔,任命,这里人事部的职责就是负责产生销售人员 再次提醒大家,不是产生具体对象,而是产生一个身份(某种职务) 在编程技术里,称人事部为:对象工厂 在Spring里,就对应着各种BeanFactory,什么是IoC,IoC即控制反转,有时候也叫做DI(依赖注入) 举报纸的例子 举商场的例子,考虑下列情形,是自己到报摊买报纸好 还是在邮局订阅,让人给送来好?,考虑下列情形,商场的例子里,是老板亲自去选拔、任命销售人员 还是老板下一个命令,让手下的人把这件事办妥了?,对于下面
16、的例子,public class HelloImpl4 implements Hello private Message 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类实例化
17、 好了,给它送过来呢,实现注入的步骤,A.在配置文件中声明好要注入的类, ,要注入的类定义,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; pub
18、lic void setMsg(Message msg) this.msg = 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()的 过程中被
19、注入好了,举例,演示spring中如何使用hibernate的session factory 请同学回答,在这个例子里,谁依赖于谁,谁被注入了? 还要注意通过这个例子,掌握属性类型为Properties和数组时怎么注入,开拓思路,业务实现类,业务接口,使用者,数据访问类A,数据访问类B,数据访问类C,开拓思路,业务实现类 数据访问类A 数据访问类B 数据访问类C,业务接口,使用者 业务接口,数据访问类A,数据访问类B,数据访问类C,给业务实现类 添加属性,给使用者类 添加属性,开拓思路,业务实现类 数据访问类A 数据访问类B 数据访问类C,业务接口,使用者 业务接口,数据访问类A,数据访问类B
20、,数据访问类C,由Spring注入 这些属性,由Spring注入 这些属性,其他,可以把所有的Bean理解为Matrix这个虚拟世界的生活着的人(相信都看过黑客帝国),他们并不知道自己的真实身份,也不知道真实世界(Spring)的存在 如果想知道自己是谁,需要实现BeanNameAware接口,有了这个接口,这个Bean就成为了崔妮绨、墨非司那种身份的人 如果想去创造这个世界,需要实现BeanFactoryAware接口,有了这个接口,这个Bean就可以成为neo(尼奥)救世主,作业,使用Spring的BeanFactory和配置文件改写网上银行项目,第 三 章,Spring AOP,什么是A
21、OP,为了理解AOP,请思考如下需求: 角色:上帝,人(每个人都有大脑) 现在上帝希望知道每个人的想法,请用面向对象的方法解决,设计登场角色,上帝,只有一个,public class God /* * 上帝的读心术 * param mind 某个人的思想 */ public void read(String mind) log.debug(上帝知道了,某个人正在想:“ + mind + ”); ,设计登场角色,人,好几十亿,public class Person private Brain brain; public void look(String thing) if(thing.equal
22、s(美女) 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 = null | thing.trim().length() = 0) return (发呆中.);
23、 else return (正在思考“ + thing + ”的问题); ,解决问题,为了要知道人们的思想,上帝决定用换脑的手段来达到目的 由于人在出生时并不知道自己的大脑是怎么来的(由Spring注入的),因此,可以在他出生时安装另一个大脑,换脑的两种方法,用继承方式 用接口方式,使用继承的方式,public class BrainExt extends Brain private God god; public void setGod(God god) this.god = god; Override public String thinking(String thing) / 告诉上帝
24、god.read(thing); return super.think(thing); ,使用接口的方式,实际上,只要能“思考”,人类不在意究竟给他的脑袋里装一个大脑还是一个石头(假如石头能思考的话) “大脑”只是一种能够思考的象征 因此,重新审视我们的设计,将大脑变成接口,变成一个抽象的概念,使用接口的方式,public class BrainProxy implements Brain private God god; private Brain brainNatural; public void setBrainNatural(Brain brainNatural) this.brain
25、Natural = brainNatural; public String thinking(String thing) god.read(thing); return brainNatural.thinking(thing); public void setGod(God god) this.god = god; ,优先选择接口而非继承,当需要进行动态代理时,接口比继承更容易实现 接口具有更好的扩展性,问题,上帝不想创建过多的代理对象,仅仅希望实现具体操作,使用Spring提供的办法,刚才的例子里,无论是使用继承还是接口进行换脑,在设计模式里都称为代理模式 请大家区分代理与被代理对象分别是谁
26、 Spring为代理提供了更方便的控制,正常操作,Spring中AOP,AOP即面向切面的编程 在AOP的概念中,将刚才的场景中的角色划分的更为细致,切面里执行 附加操作,Pointcut,正常操作之前,正常操作之后,上例中的上帝,称之为Advice(被通知对象),它知道该做什么 关于上帝何时在什么时间、地点被通知,称之为Pointcut(切入点) 对于真实的大脑,称之为Target(目标对象) 对于假的大脑,不管是真实大脑的子类还是它们实现了共同的接口,都称之为Proxy(代理对象),Spring中的Advice和Pointcut,常见的Advice和Pointcut的类型 MethodBe
27、foreAdvice AfterReturningAdvice ThrowsAdvice MethodInterceptor,配置文件相应的改动, god ,public class God implements MethodBeforeAdvice public void read(String mind) System.out.println(上帝知道了,某个人正在想:“ + mind + ”); public void before(Method method, Object args, Object target) throws Throwable read(args0.toStrin
28、g(); ,在方法执行前通知,告知你执行的方法、方法的参数s 还有目标(被代理的)对象,注意事项,Advice仅用于通知,如果需要拦截方法的调用需要使用Interceptor 无论是MethodBeforeAdvice、AfterReturningAdvice、ThrowsAdvice它们都不能改变方法的执行(本身的行为) 而Interceptor具有改变方法行为的能力,MethodInterceptor需要实现的方法,注意,一旦实现了MethodInterceptor,那些Advice(通知)就不管用了,public Object invoke(MethodInvocation mi) th
29、rows Throwable if(mi.getArguments()0.toString().indexOf(XX) 0) return (凡人,别做无谓的思考了.); /throw new RuntimeException(现在大脑一片混乱,无法思考); else return ceed(); ,改变方法的行为, 只在一念之间,Proceed让方法 继续执行,讨论,使用Spring提供的ProxyFactoryBean提供代理的好处 不必自己创建整个代理对象了,代理对象由ProxyFactoryBean产生,程序员只需要关注实现具体功能 使用ProxyFactoryBean可以
30、创建几乎任何对象的代理,减少了程序中代理类的数量,问题,但是现在上帝很郁闷,现在它必须戴上一大堆身份,弄得身上脏兮兮的 现在的结果是使得上帝依赖于Spring提供的接口,上帝离了Spring就活不了了 怎么办,Spring2.0里的AOP,使用AspectJ,使用AspectJ达到相同的效果,在AspectJ的表达中上帝是一个POJO,不需要实现特定的接口就可进行AOP操作 这个例子里,上帝在AspectJ中被成为Aspect(即切面),它的目的是执行正常逻辑之外的附加操作 与之前的Spring1.x中的AOP相比,可以把Advisor(通知)看作是知道了切入地点的Aspect,使用Aspec
31、tAOP的步骤,将BeanFactory换成ApplicationContext ApplicationContext是BeanFactory的子接口 ApplicationContext提供了更多的功能 如果将BeanFactory比作一个小作坊,那么ApplicationContext就是一个生产车间,使用AspectAOP的步骤,使用spring2.0中提供的schema样式的配置文件, ,God类的变化,public class God private static Log log = LogFactory.getLog(God.class); /* * 上帝的读心术 * param
32、mind 某个人的思想 */ public void read(String thing) log.debug(上帝知道了,某个人正在想:“ + thing + ”); ,God不需要再实现 那些Advice接口,配置文件的变化, ,它们如何对应,public class God public void read(String thing) log.debug(上帝知道了,某个人正在想:“ + thing + ”); , ,package org.yihang.aop; public interface Brain public String thinking(String thing); ,
33、其他类型的JoinPoint, - 表示已经定义好连接点的切面,Pointcut表达式,execution表示执行 public表示公共方法 第一个*表示任意返回类型 第二个*表示任意方法名 (.)表示任意参数,execution(public * *(.),更多的例子,execution(* set*(.) execution(* transfer() execution(* transfer(*) execution(* transfer(*,String) execution(* com.xyz.service.AccountService.*(.) execution(* com.xy
34、z.service.*.*(.) execution(* com.xyz.service.*.*(.),问题,如何配合切入点表达式,向切面类传递参数,使用新语法的好处,减少了代理类 在切入点的控制上更为细腻,第 四 章,Spring AOP 的应用,回顾,AOP的目的即在正常的业务操作之外增加的附加操作 通过切入点(pointcut)指名进行哪些切面(aspect)操作 ProxyFactoryBean interceptorNames targetName proxyInterfaces 拦截器(Interceptor),通知(Advice),和切面的不同(Aspect),AOP的应用,事务
35、切面 日志切面 其它附加操作切面,事务切面,在介绍事务切面之前,回顾网上银行的项目,并使用Spring IOC注入业务实现类所需的sessionFactory 实现步骤和问题思考: 实现业务接口和业务实现类(AccountService、LogService) sessionFactory如何注入的,应该注入给谁? 事务由谁来管理?,优化,现在项目经理提出需求,希望改进代码的结构,达到如下目标: transfer方法(或其它业务方法)在执行时,事务自动开始 在正确完成后,事务提交,并且关闭hibernate session 在出现RuntimeException(或其子类)异常时,事务回滚,并
36、关闭hibernate session 其他异常,仍执行提交关闭的操作,Spring的解决方案,方案A:使用事务拦截器并代理业务实现类 方案B:使用事务advice 和aspect 切面来实现事务拦截,方案A,第一步,改写AccountService业务实现类 第二步,定义ProxyFactoryBean以返回AccountService代理对象 proxyInterfaces targetName interceptorNames 这里添加事务拦截器,事务拦截器,第三步定义事务拦截器, PROPAGATION_REQUIRED PROPAGATION_REQUIRES_NEW ,事务属性以及
37、 事务管理器,Show Time,修改perties,以便观察Spring执行过程 .springframework.aop=debug .springframework.transaction=debug .springframework.orm.hibernate3=debug,事务管理器,Spring由于需要为多种数据层的实现提供集成支持,针对不同的情况,定义了各种事务管理器,一定要选择正确的事务管理器 比如: DataSourceTransactionManager 对应J
38、DBC事务 HibernateTransactionManager 对应Hibernate提供的事务 JtaTransactionManager 对应JTA事务 大多数事务管理器都需要设置dataSource(数据源)属性,对于HibernateTransactionManager可以只设置sessionFactory属性,事务属性,常见的事务属性有: 事务的传播行为 事务的隔离级别 事务是否只读 针对只读事务,Spring在某些情况下会提供优化,事务的传播行为,以下的定义可以在TransactionDefinition中找到 PROPAGATION_REQUIRED PROPAGATION_
39、SUPPORTS PROPAGATION_MANDATORY PROPAGATION_REQUIRES_NEW PROPAGATION_NOT_SUPPORTED PROPAGATION_NEVER,事务的传播行为,PROPAGATION_REQUIRED表示如果没有事务,则开始新的事务,事务已经存在,则加入当前事务 PROPAGATION_SUPPORTS 表示如果事务已经存在,则加入当前事务,如果没有事务,不会开始新事务 PROPAGATION_MANDATORY 表示必须有事务存在,并加入当前事务,否则抛出异常 PROPAGATION_REQUIRES_NEW 表示每次都开始一个全新事务
40、 PROPAGATION_NOT_SUPPORTED 表示不会开始或加入事务 PROPAGATION_NEVER 表示不会开始或加入事务,如果事务已存在,抛出异常,事务的隔离级别,以下的定义可以在TransactionDefinition中找到 ISOLATION_READ_UNCOMMITTED ISOLATION_READ_COMMITTED ISOLATION_REPEATABLE_READ ISOLATION_SERIALIZABLE,事务的隔离级别,首先明确隔离级别指的都是同一个事务中 ISOLATION_READ_UNCOMMITTED表示会读取到未提交的数据 ISOLATION_
41、READ_COMMITTED表示读取到的是已经提交的数据 ISOLATION_REPEATABLE_READ表示多次读取的数据是相同的 ISOLATION_SERIALIZABLE表示就好像没有别的用户在修改数据库中的数据一样,如何使用隔离级别,对于大多数数据库来说,事务的隔离级别是ISOLATION_READ_COMMITTED,我们不需要做更多的设置,就可以很好的工作了 将事务的隔离级别设置为ISOLATION_REPEATABLE_READ可以防止丢失更新,但这样做会严重影响系统的并发性,因此更多地是采用乐观锁的形式 ISOLATION_SERIALIZABLE并非你想象中的锁定一切!,
42、继续完成需求,第四步,完成LogService业务实现类及其代理对象的定义,修改事务拦截器 第五步,定义一个Advice实现ThrowsAdvice和MethodBeforeAdvice 以便处理日志和其它附加逻辑 第六步,将此Advice 添加至合适的位置,流程分析,当事务拦截器中的设置如下时,PROPAGATION_REQUIRED PROPAGATION_REQUIRES_NEW,执行顺序,执行AccountService代理的transfer方法 检查此代理定义的所有拦截器(有事务拦截器,和一个Advice) 根据transfer方法事务的传播规则(REQUIRED),开启一个新的事务
43、Tx_A,打开Session_A 因为Advice实现了MethodBeforeAdvice接口,因此首先执行Advice中的before方法 Before方法中,使用了LogService代理的log方法 检查LogService代理定义的拦截器(有事务拦截器) 根据log方法的传播规则(REQUIRES_NEW),又开启一个新的事务Tx_B,打开Session_B 执行log方法 当log方法成功执行,Tx_B提交,Session_B关闭 执行transfer方法 当transfer方法成功执行,Tx_A提交,Session_A关闭,当transfer发生异常,执行AccountServi
44、ce代理的transfer方法 检查此代理定义的所有拦截器(有事务拦截器,和一个Advice) 根据transfer方法事务的传播规则(REQUIRED),开启一个新的事务Tx_A,打开Session_A 因为Advice实现了MethodBeforeAdvice接口,因此首先执行Advice中的before方法 Before方法中,使用了LogService代理的log方法 检查LogService代理定义的拦截器(有事务拦截器) 根据log方法的传播规则(REQUIRES_NEW),又开启一个新的事务Tx_B,打开Session_B 执行log方法 当log方法成功执行,Tx_B提交,Se
45、ssion_B关闭 执行transfer方法 当transfer方法抛出异常,执行Advice 的afterThrowing 方法 Tx_A回滚,Session_A关闭,流程分析,当事务拦截器中的设置如下时,PROPAGATION_REQUIRED PROPAGATION_REQUIRED,执行顺序,执行AccountService代理的transfer方法 检查此代理定义的所有拦截器(有事务拦截器,和一个Advice) 根据transfer方法事务的传播规则(REQUIRED),开启一个新的事务Tx_A,打开Session_A 因为Advice实现了MethodBeforeAdvice接口,
46、因此首先执行Advice中的before方法 Before方法中,使用了LogService代理的log方法 检查LogService代理定义的拦截器(有事务拦截器) 根据log方法的传播规则( REQUIRED ),加入当前的事务Tx_A 执行log方法 执行transfer方法 当transfer方法成功执行,Tx_A提交,Session_A关闭,当transfer发生异常,执行AccountService代理的transfer方法 检查此代理定义的所有拦截器(有事务拦截器,和一个Advice) 根据transfer方法事务的传播规则(REQUIRED),开启一个新的事务Tx_A,打开Se
47、ssion_A 因为Advice实现了MethodBeforeAdvice接口,因此首先执行Advice中的before方法 Before方法中,使用了LogService代理的log方法 检查LogService代理定义的拦截器(有事务拦截器) 根据log方法的传播规则( REQUIRED ),加入当前的事务Tx_A 执行log方法 执行transfer方法 当transfer方法抛出异常,执行Advice 的afterThrowing 方法 Tx_A回滚,Session_A关闭,方案B,用Spring 2.0的新语法 可以使用新的来替换事务拦截器 使用减少配置中代理类的数量,第 五 章,S
48、pring Template技术,回顾,事务切面 日志切面 其它附加操作切面,什么是模板,回忆使用JSP进行开发的过程 先使用开发好静态的HTML页面,然后使用JSP标签替换会变化的内容 这里的关键是抽象出其中动态的、变化的内容 JSP实际就是一种模板语言,Java类中的模板,在类的开发中,也可以使用类似的技术: 将重复的代码视为代码模板,使用变化的代码去填充模板 领会模板技术,是Java编程人员登堂入室(由普通程序员架构师)的第一步,示例,第一步,审查现有代码,抽取出不同的部分(可以使用extract method),保留相似的部分 第二步,将相似代码抽取为模板类(extract class
49、) 第三步,这时候肯定有一处的调用方式不同,将其抽象为接口,注意接口的返回值、异常、参数 第四步,使用模板类替换原有实现 第五步,将原本抽取出的方法填充模板,模板和代理,在设计模式里,模板模式和代理模式有些类似 主要的区别是,代理的目的是实现正常逻辑之外的附加逻辑,甚至会改变原有操作的行为 而模板是规定了你必须执行的部分,那些每次执行行为不同的部分需要程序员自己实现 模板的例子:Struts中的Action中的execute方法,Servlet中的doGet、doPost方法 模板和代理都是设计框架必不可少的知识,Spring中的模板技术,HibernateTemplate JdbcTempl
50、ate,HibernateTemplate,HibernateTemplate里那些静态(必须执行)的部分 获取session 判断当前的方法是否处在一个事务中 异常处理部分:处理异常 Finally块:看看是否应当关闭session 这些功能已经由Spring提供好了,动态部分,动态部分需要我们自己实现:,public interface HibernateCallback Object doInHibernate(Session session) throws HibernateException, SQLException; ,演示HibernateTemplate的使用,小结,其实 H
51、ibernateTemplate在Spring集成早些版本的hibernate(2.x)时是非常有用的,它将session与当前线程进行绑定,确保了进行多次方法调用后事务的提交回滚和session的关闭都是针对同一个session 目前的Hibernate(3.x)中的sessionFactory.getCurrentSession();提供了相同的功能,因此template的功能有所重复,你可以根据自己情况选择使用 请对比WebBank工程中的HibernateAccountServiceNew HibernateAccountServiceTx两个类来理解它们的异同,JDBCTemplat
52、e,使用JDBC与Hibernate模板的不同之处: JDBC模板的使用依赖于javax.sql.DataSource,而Hibernate模板的使用依赖于org.hibernate.SessionFactory 相同之处: 它们都会应用事务切面,自动处理事务的提交和回滚 无须自己打开关闭Session或Connection,Javax.sql.DataSource,我们以前介绍过,DataSource一般是由应用服务器提供的,用于获取数据库连接的连接工厂 它同时集成了连接池的功能 为了便于不依赖于容器,方便在容器外部进行测试,Spring提供了一个实现了DataSource接口的类Drive
53、rManagerDataSource,它仅仅是对数据库直连方式的一个简单封装,不提供连接池的功能,事务管理器,为了配合JDBC的事务管理,需要将事务管理器的实现换为DataSourceTransactionManager,演示JDBCTemplate的使用,三层结构之DAO,什么是DAO DAO即Data Access Object,在hibernate等持久层框架出现之前,DAO用于解耦业务逻辑与底层的数据访问之间的联系(能够方便的在不同的数据库切换) DAO也是通过DAO接口DAO实现类来完成解耦操作的 如果已经使用了一种持久层框架,那么DAO基本上是多余的,DAO举例,例如在我们现有的设
54、计里,JDBCLogService和JDBCAccountService这两个实现类都会访问数据库 在业务逻辑代码之外,存在很多与之无关的数据访问代码 并且,如果现在访问的其它类型的数据库,那么SQL语句会有差异 因此,将这些数据访问功能独立于业务逻辑之外,是一种好的解决方案,实现思路,业务逻辑实现类中不需要知道如DataSource对象,也无须实现findAccount、insertTransferRecord、updateAccount等方法,它只需要知道一个或几个DAO接口即可 DAO实现负责以上方法的实现,跟数据源对象打交道,如果需要使用不同的数据库,那么分别实现相应的DAO实现类 业
55、务逻辑实现类中声明一个类型为DAO接口的属性,由Spring依赖注入DAO实现,作业,使用DAO+JDBC来修改课堂示例,第 六 章,Spring 与表现层集成,回顾,Spring是如何集成业务逻辑层的? 通过接口实现类的方式解耦业务层与其它层,主要是用到了控制反转(依赖注入)的办法 通过AOP的方法,分离事务、日志等切面操作,让业务逻辑更为清晰 Spring是如何集成持久层的? 通过模板技术,让具体的持久层实现无须考虑如何获得连接,关闭连接(或指session)等繁琐操作,使程序员专心处理数据CURD操作 如果使用了hibernate等持久层框架,DAO就不重要了,表现层集成,Spring可
56、以与多种表现层技术实现集成,其实与表现层集成以我的理解就是业务逻辑如何被调用的问题,可以分以下几个方面 与某种Web框架相集成,如Struts,DWR等 与某种java桌面应用程序相集成,如Swing来调用业务逻辑 与某种其它语言的应用程序集成,如.net的程序,与Struts集成,Spring与Struts集成有两种方式: 使用Struts调用Spring。优点是直接了当,容易理解,缺点是无法使用Spring的依赖注入 使用Spring来管理Struts中的Action。优点是可以为Action注入业务逻辑实现,与Struts集成,方法A. 使用Struts调用Spring 步骤: 添加Spring提供的 ContextLoaderListener和contextConfigLocation属性以指明Spring配置文件的位置,其原理是使用了Listener
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论