1. 谈谈你mvc的理解
MVC是Model—View—Controler的简称。即模型—视图—控制器。MVC是一种设计模式,它强制性的把应用程序的输入、处理和输出分开。
MVC中的模型、视图、控制器它们分别担负着不同的任务。
视图: 视图是用户看到并与之交互的界面。视图向用户显示相关的数据,并接受用户的输入。视图不进行任何业务逻辑处理。
模型: 模型表示业务数据和业务处理。相当于JavaBean。一个模型能为多个视图提供数据。这提高了应用程序的重用性
控制器: 当用户单击Web页面中的提交按钮时,控制器接受请求并调用相应的模型去处理请求。
然后根据处理的结果调用相应的视图来显示处理的结果。
MVC的处理过程:首先控制器接受用户的请求,调用相应的模型来进行业务处理,并返回数据给控制器。控制器调用相应的视图来显示处理的结果。并通过视图呈现给用户。
Struts
1. struts1.2和struts2.0的区别?如何控制两种框架中的单例模式?
Action类:
Struts1要求Action类继承一个抽象基类。Struts1的一个普遍问题是使用抽象类编程而不是接口。
Struts2 Action类可以实现一个Action接口,也可实现其他接口,使可选和定制的服务成为可能。Struts2提供一个ActionSupport基类去 实现常用的接口。Action接口不是必须的,任何有execute标识的POJO对象都可以用作Struts2的Action对象。
线程模式:
Struts1Action是单例模式并且必须是线程安全的,因为仅有Action的一个实例来处理所有的请求。单例策略限制了Struts1Action能作的事,并且要在开发时特别小心。Action资源必须是线程安全的或同步的。
Struts2Action对象为每一个请求产生一个实例,因此没有线程安全问题。(实际上,servlet容器给每个请求产生许多可丢弃的对象,并且不会导致性能和垃圾回收问题)
Servlet依赖:
Struts1Action 依赖于ServletAPI ,因为当一个Action被调用时HttpServletRequest 和HttpServletResponse 被传递给execute方法。
Struts2 Action不依赖于容器,允许Action脱离容器单独被测试。如果需要,Struts2Action仍然可以访问初始的request和response。但是,其他的元素减少或者消除了直接访问HttpServetRequest和HttpServletResponse的必要性。
可测性:
测试Struts1Action的一个主要问题是execute方法暴露了servlet API(这使得测试要依赖于容器)。一个第三方扩展--StrutsTestCase--提供了一套Struts1的模拟对象(来进行测试)。
Struts2 Action可以通过初始化、设置属性、调用方法来测试,“依赖注入”支持也使测试更容易。
捕获输入:
Struts1使用ActionForm对象捕获输入。所有的ActionForm必须继承一个基类。因为其他JavaBean不能用作ActionForm,开发者经 常创建多余的类捕获输入。动态Bean(DynaBeans)可以作为创建传统ActionForm的选择,但是,开发者可能是在重新描述(创建)已经存 在的JavaBean(仍然会导致有冗余的javabean)。
Struts2直接使用Action属性作为输入属性,消除了对第二个输入对象的需求。输入属性可能是有自己(子)属性的rich对象类型。Action属性能够通过 web页面上的taglibs访问。Struts2也支持ActionForm模式。rich对象类型,包括业务对象,能够用作输入/输出对象。这种 ModelDriven 特性简化了taglib对POJO输入对象的引用。
表达式语言:
Struts1整合了JSTL,因此使用JSTL EL。这种EL有基本对象图遍历,但是对集合和索引属性的支持很弱。
Struts2可以使用JSTL,但是也支持一个更强大和灵活的表达式语言--"ObjectGraph Notation Language" (OGNL).
绑定值到页面(view):
Struts1使用标准JSP机制把对象绑定到页面中来访问。
Struts2 使用"ValueStack"技术,使taglib能够访问值而不需要把你的页面(view)和对象绑定起来。ValueStack策略允许通过一系列名称相同但类型不同的属性重用页面(view)。
类型转换:
Struts1 ActionForm 属性通常都是String类型。Struts1使用Commons-Beanutils进行类型转换。每个类一个转换器,对每一个实例来说是不可配置的。
Struts2使用OGNL进行类型转换。提供基本和常用对象的转换器。
校验:
Struts1支持在ActionForm的validate方法中手动校验,或者通过Commons Validator的扩展来校验。同一个类可以有不同的校验内容,但不能校验子对象。
Struts2支持通过validate方法和XWork校验框架来进行校验。XWork校验框架使用为属性类类型定义的校验和内容校验,来支持chain校验子属性
Action执行的控制:
Struts1支持每一个模块有单独的Request Processors(生命周期),但是模块中的所有Action必须共享相同的生命周期。
Struts2支持通过拦截器堆栈(Interceptor Stacks)为每一个Action创建不同的生命周期。堆栈能够根据需要和不同的Action一起使用。
2. Struts2/webwork的工作机制,它有哪些标签
Struts 2框架的大致处理流程如下:
浏览器发送请求,例如请求/mypage.action、/reports/myreport.pdf等。
核心控制器FilterDispatcher根据请求决定调用合适的Action。
WebWork的拦截器链自动对请求应用通用功能,例如workflow、validation或文件上传等功能。
回调Action的execute方法,该execute方法先获取用户请求参数,然后执行某种数据库操作,既可以是将数据保存到数据库,也可以从数据库中检索信息。实际上,因为Action只是一个控制器,它会调用业务逻辑组件来处理用户的请求。
Action的execute方法处理结果信息将被输出到浏览器中,可以是HTML页面、图像,也可以是PDF文档或者其他文档。此时支持的视图技术非常多,既支持JSP,也支持Velocity、FreeMarker等模板技术。
拦截器
拦截器(Interceptor)是Struts 2的核心组成部分。很多功能(Feature)都是构建在拦截器基础之上的,例如文件的上传和下载、国际化、转换器和数据校验等,Struts 2利用内建的拦截器,完成了框架内的大部分操作。在Struts 2文档中对拦截器的解释为——拦截器是动态拦截Action调用的对象。它提供了一种机制,使开发者可以定义一个特定的功能模块,这个模块可以在Action执行之前或者之后运行,也可以在一个Action执行之前阻止Action执行。同时也提供了一种可以提取Action中可重用的部分的方式
把程序看作是一个顺序执行的流,在执行Action的代码之前或之后,拦截器会打断Action的执行,让程序先执行拦截器的代码,这也许就是为什么把它叫做拦截器的原因。有的时候,拦截器还会阻止Action的执行,比如说在验证失败的情况下,应该让程序返回到输入界面让用户重新输入。
ValueStack
当访问一个action的时候,此时struts2会把整个action压入valuestack的顶部,此时valuestack就一个action对象
我们通常会写stack.set(key1,value1)或者statck.setvalue(key2,value2) 这两个是有区别的,前者会在valuestack压入一个hashmap,并将key1,value1植入该hashmap 那么此时valuestack会有两个对象,顶部是hashmap,底部是action 后者会将key2,value2直接植入到顶部的对象,通常是action,如果action没有相应的set方法,那么执行这个方法等于白搭,你如果此时执行valuestack.findvalue就会为空
我们通常会在多个拦截器传递数据,正如前面所说,你必须得再action中写入set方法,否则无效,如果你不想写,那么请用valuestack.set,这样就不用改写action. 但又存在一个隐患,如果拦截器1中你写了valuestack.set,然后你在拦截器2中同findvalue获取了该值,这没有问题,假设你突然想在拦截器2中传一个值给action ,问题就暴露了,你会在拦截器2中像平常一样写statck.setvalue,然后在action 中加上 set,满以为可以传递过去,其实不行,因为此时栈顶是一个map,而非action,你此时是将值植入到map,而非action,所以传值失败。
valuestack作为拦截器、action,甚至页面传递数据的一个数据结构,特别是当栈中存在多个对象的时候,必须注意栈中对象的顺序以免产生一些恼人的问题。
Hibernate
1. 什么是Hibernate的并发机制?怎么去处理并发问题?
Hibernate并发机制:
a、Hibernate的Session对象是非线程安全的,对于单个请求,单个会话,单个的工作单元(即单个事务,单个线程),它通常只使用一次,
然后就丢弃。
如果一个Session 实例允许共享的话,那些支持并发运行的,例如Http request,session beans将会导致出现资源争用。
如果在Http Session中有hibernate的Session的话,就可能会出现同步访问Http Session。只要用户足够快的点击浏览器的“刷新”,
就会导致两个并发运行的线程使用同一个Session。
b、多个事务并发访问同一块资源,可能会引发第一类丢失更新,脏读,幻读,不可重复读,第二类丢失更新一系列的问题。
解决方案:设置事务隔离级别。
Serializable:串行化。隔离级别最高
Repeatable Read:可重复读
Read Committed:已提交数据读
Read Uncommitted:未提交数据读。隔离级别最差
设置锁:乐观锁和悲观锁。
乐观锁:使用版本号或时间戳来检测更新丢失,在<class>的映射中设置optimistic-lock="all"可以在没有版本或者时间戳属性映射的情况下实现 版本检查,此时Hibernate将比较一行记录的每个字段的状态 行级悲观锁:Hibernate总是使用数据库的锁定机制,从不在内存中锁定对象!只要为JDBC连接指定一下隔 离级别,然后让数据库去搞定一切就够了。类LockMode 定义了Hibernate所需的不同的锁定级别:LockMode.UPGRADE,LockMode.UPGRADE_NOWAIT,LockMode.READ;
2. Hibernate与jdbc的联系
hibernate是jdbc的轻量级封装,包括jdbc的与数据库的连接(用hibernate.property的配置文件实现当然本质是封装了jdbc的forname),
和查询,删除等代码,都用面向对象的思想用代码联系起来,hibernate通过hbm 配置文件把po类的字段和数据库的字段关联起来比如数据库的id,
在po类中就是praviteLong id; public Long getId() ;public setId(Long id);
然后hql语句也是面向对象的,它的查询语句不是查询数据库而是查询类的,这些实现的魔法就是xml文件,其实hibernate=封装的jdbc+xml文件
3. Hibernate与spring的联系
hibernate中的一些对象可以给Spring来管理,让Spring容器来创建hibernate中一些对象实例化。例如:SessionFactory,HibernateTemplate等。
Hibernate本来是对数据库的一些操作,放在DAO层,而Spring给业务层的方法定义了事务,业务层调用DAO层的方法,很好的将Hibernate的操作也加入到事务中来了。
4. Hibernate自带的分页机制是什么?如果不使用Hibernate自带的分页,则采用什么方式分页?
1、hibernate自带的分页机制:获得Session对象后,从Session中获得Query对象。用Query.setFirstResult():设置要显示的第一行数据,
Query.setMaxResults():设置要显示的最后一行数据。
2、不使用hibernate自带的分页,可采用sql语句分页,
如:5:为每页显示的记录,2为当前页: select * top 5from table where tabId not in (select tabId top (2-1)*5 from table);
5. update()和saveOrUpdate()的区别?update()方法操作的对象必须是持久化了的对象。也就是说,如果此对象在数据库中不存在的话,就不能使用update()方法。
saveOrUpdate()方法操作的对象既可以使持久化了的,也可以使没有持久化的对象。如果是持久化了的对象调用saveOrUpdate()则会
更新数据库中的对象;如果是未持久化的对象使用此方法,则save到数据库中。
6. hibernate的三种状态之间如何转换
当对象由瞬时状态(Transient)一save()时,就变成了持久化状态。
当我们在Session里存储对象的时候,实际是在Session的Map里存了一份,
也就是它的缓存里放了一份,然后,又到数据库里存了一份,在缓存里这一份叫持久对象(Persistent)。
Session 一 Close()了,它的缓存也都关闭了,整个Session也就失效了,
这个时候,这个对象变成了游离状态(Detached),但数据库中还是存在的。
当游离状态(Detached)update()时,又变为了持久状态(Persistent)。
当持久状态(Persistent)delete()时,又变为了瞬时状态(Transient),
此时,数据库中没有与之对应的记录。
7. hibernate拒绝连接、服务器崩溃的原因?最少写5个
1. db没有打开
2. 网络连接可能出了问题
3. 连接配置错了
4. 驱动的driver,url是否都写对了
5. LIB下加入相应驱动,数据连接代码是否有误
6. 数据库配置可能有问题
7. 当前联接太多了,服务器都有访问人数限制的
8. 服务器的相应端口没有开,即它不提供相应的服务
9 hibernate有哪些缓存,分别怎么使用?
10 你对hibernate的了解到了一个什么样的程度?
11 写出一个sql语句体现hibernate中一对多的关系
8. hibernate介绍
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任。
Hibernate的核心接口一共有5个,分别为:Session、SessionFactory、Transaction、Query和Configuration。这5个核心接口在任何开发中都会用到。通过这些接口,不仅可以对持久化对象进行存取,还能够进行事务控制。下面对这五个核心接口分别加以介绍。
·Session接口:Session接口负责执行被持久化对象的CRUD操作(CRUD的任务是完成与数据库的交流,包含了很多常见的SQL语句。)。但需要注意的是Session对象是非线程安全的。同时,Hibernate的session不同于JSP应用中的HttpSession。这里当使用session这个术语时,其实指的是Hibernate中的session,而以后会将HttpSesion对象称为用户session。
·SessionFactory接口:SessionFactroy接口负责初始化Hibernate。它充当数据存储源的代理,并负责创建Session对象。这里用到了工厂模式。需要注意的是SessionFactory并不是轻量级的,因为一般情况下,一个项目通常只需要一个SessionFactory就够,当需要操作多个数据库时,可以为每个数据库指定一个SessionFactory。
·Configuration接口:Configuration接口负责配置并启动Hibernate,创建SessionFactory对象。在Hibernate的启动的过程中,Configuration类的实例首先定位映射文档位置、读取配置,然后创建SessionFactory对象。
·Transaction接口:Transaction接口负责事务相关的操作。它是可选的,开发人员也可以设计编写自己的底层事务处理代码。
·Query和Criteria接口:Query和Criteria接口负责执行各种数据库查询。它可以使用HQL语言或SQL语句两种表达方式。
Hibernate 中提供了两级Cache,第一级别的缓存是Session级别的缓存,它是属于事务范围的缓存。这一级别的缓存由hibernate管理的,一般情况下无需进行干预;第二级别的缓存是SessionFactory级别的缓存,它是属于进程范围或群集范围的缓存。这一级别的缓存可以进行配置和更改,并且可以动态加载和卸载。 Hibernate还为查询结果提供了一个查询缓存,它依赖于第二级缓存。
1. 一级缓存和二级缓存的比较:第一级缓存第二级缓存存放数据的形式相互关联的持久化对象对象的散装数据缓存的范围事务范围,每个事务都有单独的第一级缓存进程范围或集群范围,缓存被同一个进程或集群范围内的所有事务共享并发访问策略由于每个事务都拥有单独的第一级缓存,不会出现并发问题,无需提供并发访问策略由于多个事务会同时访问第二级缓存中相同数据,因此必须提供适当的并发访问策略,来保证特定的事务隔离级别数据过期策略没有提供数据过期策略。处于一级缓存中的对象永远不会过期,除非应用程序显式清空缓存或者清除特定的对象必须提供数据过期策略,如基于内存的缓存中的对象的最大数目,允许对象处于缓存中的最长时间,以及允许对象处于缓存中的最长空闲时间物理存储介质内存内存和硬盘。对象的散装数据首先存放在基于内在的缓存中,当内存中对象的数目达到数据过期策略中指定上限时,就会把其余的对象写入基于硬盘的缓存中。缓存的软件实现在Hibernate的Session的实现中包含了缓存的实现由第三方提供,Hibernate仅提供了缓存适配器(CacheProvider)。用于把特定的缓存插件集成到Hibernate中。启用缓存的方式只要应用程序通过Session接口来执行保存、更新、删除、加载和查询数据库数据的操作,Hibernate就会启用第一级缓存,把数据库中的数据以对象的形式拷贝到缓存中,对于批量更新和批量删除操作,如果不希望启用第一级缓存,可以绕过Hibernate API,直接通过JDBCAPI来执行指操作。用户可以在单个类或类的单个集合的粒度上配置第二级缓存。如果类的实例被经常读但很少被修改,就可以考虑使用第二级缓存。只有为某个类或集合配置了第二级缓存,Hibernate在运行时才会把它的实例加入到第二级缓存中。用户管理缓存的方式第一级缓存的物理介质为内存,由于内存容量有限,必须通过恰当的检索策略和检索方式来限制加载对象的数目。Session的evit()方法可以显式清空缓存中特定对象,但这种方法不值得推荐。第二级缓存的物理介质可以是内存和硬盘,因此第二级缓存可以存放大量的数据,数据过期策略的maxElementsInMemory属性值可以控制内存中的对象数目。管理第二级缓存主要包括两个方面:选择需要使用第二级缓存的持久类,设置合适的并发访问策略:选择缓存适配器,设置合适的数据过期策略。
2. 一级缓存的管理:当应用程序调用Session的save()、update()、savaeOrUpdate()、get()或load(),以及调用查询接口的 list()、iterate()或filter()方法时,如果在Session缓存中还不存在相应的对象,Hibernate就会把该对象加入到第一级缓存中。当清理缓存时,Hibernate会根据缓存中对象的状态变化来同步更新数据库。 Session为应用程序提供了两个管理缓存的方法: evict(Object obj):从缓存中清除参数指定的持久化对象。 clear():清空缓存中所有持久化对象。
3. 二级缓存的管理:
3.1. Hibernate的二级缓存策略的一般过程如下:
1) 条件查询的时候,总是发出一条select * from table_name where …. (选择所有字段)这样的SQL语句查询数据库,一次获得所有的数据对象。
2) 把获得的所有数据对象根据ID放入到第二级缓存中。
3) 当Hibernate根据ID访问数据对象的时候,首先从Session一级缓存中查;查不到,如果配置了二级缓存,那么从二级缓存中查;查不到,再查询数据库,把结果按照ID放入到缓存。
4) 删除、更新、增加数据的时候,同时更新缓存。
Hibernate的二级缓存策略,是针对于ID查询的缓存策略,对于条件查询则毫无作用。为此,Hibernate提供了针对条件查询的Query Cache。
3.2. 什么样的数据适合存放到第二级缓存中? 1 很少被修改的数据 2 不是很重要的数据,允许出现偶尔并发的数据 3 不会被并发访问的数据 4 参考数据,指的是供应用参考的常量数据,它的实例数目有限,它的实例会被许多其他类的实例引用,实例极少或者从来不会被修改。
3.3. 不适合存放到第二级缓存的数据? 1 经常被修改的数据 2 财务数据,绝对不允许出现并发 3 与其他应用共享的数据。
3.4. 常用的缓存插件 Hibernater 的二级缓存是一个插件,下面是几种常用的缓存插件:
EhCache:可作为进程范围的缓存,存放数据的物理介质可以是内存或硬盘,对Hibernate的查询缓存提供了支持。
OSCache:可作为进程范围的缓存,存放数据的物理介质可以是内存或硬盘,提供了丰富的缓存数据过期策略,对Hibernate的查询缓存提供了支持。
SwarmCache:可作为群集范围内的缓存,但不支持Hibernate的查询缓存。
JBossCache:可作为群集范围内的缓存,支持事务型并发访问策略,对Hibernate的查询缓存提供了支持。
3.5. 配置二级缓存的主要步骤:
1) 选择需要使用二级缓存的持久化类,设置它的命名缓存的并发访问策略。这是最值得认真考虑的步骤。
2) 选择合适的缓存插件,然后编辑该插件的配置文件。
10. Hibernate和ibatis的区别
1. 易用性:ibatis非常简单易学,会写SQL就会ibatis。hibernate相对较复杂,有一定的学习曲线。
2. 开发效率:ibatis需要手写sql语句,也可以生成一部分,hibernate则基本上可以自动生成,偶尔会写一些hql。对于具有传统增删改差功能的系统,,ibatis的工作量比hibernate要大很多。
3. 性能:系统数据处理量巨大,性能要求苛刻时,在这种情况下ibatis更灵活且便于调优。
4. 移植性:ibatis的sql语句语法、关键字等和具体数据库绑定,无法移植。Hibernate在移植性方面更有优势。
5. 适用场景:任何技术选型都是以业务、性能需求为依据的。当系统属于二次开发,或者系统数据量大,对性能要求高,使用ibatis。当系统有较简单的增删改查功能,建议使用hibernate提高工作效率。当然也可以将二者均集成进系统框架,根据需求使用。
Spring
1. 好好理解下面的话,可以提升你对Spring的理解
Spring框架的核心思想我们可以用两个字来描述,那就是"解耦"。应用程序的各个部分之间(包括代码内部和代码与平台之间)尽量形成一种松耦合的结构,使得应用程序有更多的灵活性。应用内部的解耦主要通过一种称为控制反转(IOC)的技术来实现。控制反转的基本思想就是本来由应用程序本身来主动控制的调用等逻辑转变成由外部配置文件来被动控制。对spring来讲,就是由spring来负责控制对象的生命周期和维护对象间的关系。通常我们用一个所谓的好莱坞原则(Don't call me. I willcall you.)来比喻这种控制反转的关系。由于控制反转的概念相对比较广泛,很多应用服务器实际上也实现了不同程度的控制反转技术,只是这些应用服务器对应用程序的侵入性太强。因此MartinFowler专门写了一篇文章讨论控制反转这个概念,并提出一个描述更为准确的概念,叫依赖注入(DependencyInjection)。
Spring框架中的各个部分都充分使用了这种依赖注入的技术实现,从而给应用以最大的灵活度。实际上,这种依赖注入的参数化应用控制并不是Spring的首创,比如IBM的多渠道应用整合平台(BranchTransformation Toolkit,BTT)很早就采用了这种外部参数化控制的技术。BTT中的"对象工厂"与Spring框架中的BeanFactory也有着异曲同工之妙。
Spring框架另外一个比较重要的技术是它对于面向切面的编程(AOP)的支持。随着应用复杂度的逐渐上升和对应用灵活性要求的提高,IT逻辑和业务逻辑尽量分离的呼声也越来越高。AOP技术作为实现这种分离的一种比较好的途径而越来越受到大家的重视。Spring提供的是一种动态AOP实现,也即通过代理模式动态地在目标对象的方法前后插入相应的处理代码。应用程序与底层应用服务器平台的解耦也可以借助AOP技术来实现。Spring内置的AOP支持是一种锦上添花的功能。它使得一些本来必须由容器支持的功能,比如事务控制可以脱离开容器运行,从而达到"瘦身"的目的。这也是为什么Spring框架常被人成为轻量级容器的一个原因。
2. spring是什么?根据你的理解详细谈谈你的见解。
◆目的:解决企业应用开发的复杂性
◆功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能
◆范围:任何Java应用
简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
◆轻量——从大小与开销两方面而言Spring都是轻量的。完整的Spring框架可以在一个大小只有1MB多的JAR文件里发布。并且Spring所需的处理开销也是微不足道的。此外,Spring是非侵入式的:典型地,Spring应用中的对象不依赖于Spring的特定类。
◆控制反转——Spring通过一种称作控制反转(IoC)的技术促进了松耦合。当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。你可以认为IoC与JNDI相反——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。
◆面向切面——Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务()管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。
◆容器——Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建——基于一个可配置原型(prototype),你的bean可以创建一个单独的实例或者每次需要时都生成一个新的实例——以及它们是如何相互关联的。然而,Spring不应该被混同于传统的重量级的EJB容器,它们经常是庞大与笨重的,难以使用。
◆框架——Spring可以将简单的组件配置、组合成为复杂的应用。在Spring中,应用对象被声明式地组合,典型地是在一个XML文件里。Spring也提供了很多基础功能(事务管理、持久化框架集成等等),将应用逻辑的开发留给了你。
所有Spring的这些特征使你能够编写更干净、更可管理、并且更易于测试的代码。它们也为Spring中的各种模块提供了基础支持。
3. 项目中如何体现Spring中的切面编程,距离说明。
面向切面编程:主要是横切一个关注点,将一个关注点模块化成一个切面。在切面上声明一个通知(Advice)和切入点(Pointcut); 通知: 是指在切面的某个特定的连接点(代表一个方法的执行。通过声明一个org.aspectj.lang.JoinPoint类型的参数可以使通知(Advice)的主体部分获得连接点信息。)上执行的动作。通知中定义了要插入的方法。切入点:切入点的内容是一个表达式,以描述需要在哪些对象的哪些方法上插入通知中定义的方法。
项目中用到的Spring中的切面编程最多的地方:声明式事务管理。
a、定义一个事务管理器
b、配置事务特性(相当于声明通知。一般在业务层的类的一些方法上定义事务)
c、配置哪些类的哪些方法需要配置事务(相当于切入点。一般是业务类的方法上)
定义的5个不同的事务隔离级别:
DEFAULT:默认的隔离级别,使用数据库默认的事务隔离级别
READ_COMMITTED:保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。
READ_UNCOMMITTED:这是事务最低的隔离级别,它充许别外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。
REPEATABLE_READ:这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免不可重复读。
SERIALIZABLE:这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。
propagation定义了7个事务传播行为
REQUIRED: 如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。
SUPPORTS: 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行。但是对于事务同步的事务管理器,SUPPORTS与不使用事务有少许不同。
REQUIRES_NEW 总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。
NOT_SUPPORTED 总是非事务地执行,并挂起任何存在的事务。
NEVER 总是非事务地执行,如果存在一个活动事务,则抛出异常
NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, 则按TransactionDefinition.PROPAGATION_REQUIRED属性执行。
嵌套事务一个非常重要的概念就是内层事务依赖于外层事务。外层事务失败时,会回滚内层事务所做的动作。而内层事务操作失败并不会引起外层事务的回滚。
REQUIRED应该是我们首先的事务传播行为。它能够满足我们大多数的事务需求。
4. FactoryBean和BeanFactory
Spring 的容器有两个接口: BeanFactory可和 ApplicationContext,这两个接口的实例也被称为 Spring 上下文,它们都是产生 bean 的工厂, bean 是 Spring 工厂产生的实例。在Spring 产生 bean 实例时,需要知道每个 bean 的实现类,而 bean 实例的使用者面向接口,无须关心 bean 实例的实现类。因为 Spring 工厂负责维护 bean 实例的实例化,所以使用者无须关心实例化。
bean定义通常使用 XML 配置文件。正确定义的 bean 由 Spring 提供实例化,以及依赖关系的注入。 bean 实例通过 BeanFactory 访问。对于大部分J2EE 应用, bean 通过AppliactionContext 提供访问,因为 AppliactionContext是 BeanFactory 的子接口,提供比BeanFactory 更多的功能。
org.springframework.beans.factory.FactoryBean是一个接口,是Spring中用于定义自定义服务的核心接口,他本身是在bean工厂中定义的一个bean,同时又是用于创建另一个Spring服务对象的工厂。
5. spring的依赖注入方式有哪几种
spring的IOC有三种注入方式 第一是根据属性注入 也叫set方法注入;第二种是根据构造方法进行注入;第三种是根据注解进行注入