问题及答案来源自《Java程序员面试笔试宝典》第五章 Java Web 5.3 框架
11、什么是IoC?
IoC:控制反转(Inverse of Control, IoC),有时候也被称为依赖注入,是一种降低对象之间耦合关系的一种设计思想
一般而言,在分层体系结构中,都是上层调用下层的接口,上层依赖于下层的执行,即调用者依赖于被调用者。
而通过Ioc方式,使得上层不再依赖于下层的接口,即通过一定的机制来选择不同的下层实现,完成控制反转,使得
由调用着决定被调用者。IoC通过注入一个实例化的对象来达到解耦合的目的
使用这种方法后,对象不会被显式的调用,而是根据需求通过IoC容器(例如Spring)来提供。 采用IoC机制能够提高系统
的可扩展性,如果对象之间通过显式调用进行交互会导致调用者与被调用者存在着非常紧密的联系,其中一方的改动会
导致程序出现很多的改动
实际案例如下:
要为一家茶店提供一套管理系统,在这家商店刚开业时只卖绿茶,随着规模的扩大或者根据具体销售量,未来可能会随时
改变茶的类型,例如红茶等,传统的实现方式会针对茶抽象化一个基类,绿茶类只需要继承自该基类即可,如下图所示:
采用该实现方法后,在需要使用GreenTea时,只需要执行以下代码即可:AbstractTea t = new GreenTea(),当然,
这种方法是可以满足当前设计要求的,但是该方法的可扩展性不好,存在着不恰当的地方,例如商家发现绿茶的销售
并不好,决定开始销售红茶,那么需要实现一个BlackTea类,并且让这个类继承自AbstractTea即可。但是,系统中用到
的AbstractTea t = new GreenTea()都需要改为AbstractTea t = new BlackTea(),而这种创建对象实例额方法往往会导致
程序的改动量非常大。
那怎么样才能增强系统的可扩展性呢?– 可以采用设计模式中的工厂模式
此时可以使用设计模式中的工厂模式来把创建对象的行为包装起来:
通过以上的方法,可以把创建对象的过程委托给TeaFactory来完成,在需要使用Tea对象时,只需要调用Factory类的
getTea方法即可,具体创建对象的逻辑在TeaFactory中来实现,那么当商家需要把绿茶替换为红茶时,系统只需要改动
TeaFactory中创建对象的逻辑即可,采用了工厂模式后,只需要在一个地方做改动就可以满足要求,这样就增强了系统
的可扩展性。虽然采用工厂设计模式后,增强了系统的可扩展性,但是本质上来讲,工程模式只不过把程序中会变动的
逻辑移动到工厂类里面了,当系统中类较多时,在系统扩展时需要经常改动工厂类中的代码。而采用IoC设计思想后,程序
会有更好的扩展性
Spring框架IoC的实现方法:
spring框架在采用Ioc后的实现方法是将上面的TeaFactory通过Ioc容器通过配置文件来加载被调用对象,同时把被调用的对象
的实例化对象通过构造函数或者set方法的形式注入到调用者对象中
12、什么是AOP?
AOP:
面向切面编程(Aspect-oriented Programming,AOP)是对面向对象开发的一种补充,它允许开发人员在不改变原来模型的
基础上动态的修改模型以满足新的需求,例如,开发人员可以在不改变原来业务逻辑模型的基础上可以动态的增加日志、
安全或异常处理的功能。
13、什么是Spring框架?
Spring框架:
Spring是一个J2EE框架,这个框架提供了对轻量级IoC的良好支持,同时也提供了对AOP技术非常好的封装。
相比其他框架,Spring框架的设计更加模块化,框架内的每个模块都能完成特定的工作,而且各个模块可以独立的
运行,不会相互牵制,因此,在使用Spring框架开发时,开发人员可以使用整个框架,也可以只使用框架内的一部分
模块,例如只使用Spring AOP模块来实现日志管理功能,而不需要使用其他模块。
Spring框架主要由7个模块组成,分别是Spring AOP、Spring ORM、Spring DAO、Spring Web、Spring Context、
Spring Web MVC、Spring Core等。
Spring框架图:
下面是各模块的作用:
Spring AOP:采用了面向切面编程的思想,使Spring框架管理的对象支持AOP,同时这个模块也提供了事务管理,
可以不依赖具体的EJB组件,就可以将事务管理集成到应用程序中
Spring ORM:提供了对现有ORM框架的支持,例如Hibernate、JDO等
Spring DAO:提供了对数据访问对象(Data Access Object,DAO)模式和JDBC的支持。DAO可以实现把业务逻辑与
数据库访问的代码实现分离,从而降低代码的耦合度。通过对JDBC的抽象,简化了开发工作,同时简化了对异常的
处理(可以很好的处理不同数据库厂商抛出的异常)
Spring Web:提供了Servlet监听器的Client和Web应用的上下文。同时还集成了一些现有的Web框架,例如Structs
Spring Context:扩展核心容器,提供了Spring上下文环境,给开发人员提供了很多有用的服务
Spring MVC:提供了一个构件Web应用程序的MVC的实现
Spring Core:Spring框架的核心容器,它提供了Spring框架的基本功能,这个模块中最主要的一个组件为BeanFactory,
它使用工厂模式来创建所需的对象。同时BeanFactory使用IOC思想,通过读取XML文件的方式来实例化对象,可以说
BeanFactory提供了组件生命周期的管理,组建的创建、装配、销毁等功能
14、什么是Hibernate?
Hibernate:
Hibernate是一个开放源代码的对象关系映射(ORM)框架,它不仅可以允许在J2EE容器中,也可以运行在J2EE容器外
它对JDBC进行了轻量级封装,任何可以使用JDBC的地方都可以用Hibernate代替
Hibernate实现了Java对象与关系数据库记录的映射关系,简化了开发人员访问数据库的流程,提高软件开发效率
Hibernate的五个核心接口:
(1)Configuration接口:
作用:配置hibernate,启动hibernate
hibernate应用通过Configuration执行关系-映射文件的位置或者动态配置hibernate属性,最后创建SessionFactory实例对象
在hibernate的hiberante.cfg.xml文件配置中,会有这么一句话:
<mapping resource="com/lanhuigu/hibernate/entity/Customer.hbm.xml" />
这句就是指定关系-映射文件的位置。
(2)SessionFactory接口:
作用:初始化hibernate,一个SessionFactory对应一个实例数据源,创建session接口对象
SessionFactory特点:
- 线程安全,一个实例多个线程共享。
- 不能随意创建和销毁,因为是重量级的。一个数据库只需创建一个SessionFactory实例,初始化时创建。如果同时访问多个数据库,需要对应每个数据库创建对应的实例。否则线程共享数据时,发生数据混乱。
(3)Session接口:
作用:负责数据的保存,更新,删除,加载和查询对象
Session接口的特点:
- 线程不安全,避免多个线程共享一个session。
- 是轻量级的,创建和销毁消费资源少,被称为持久化管理器
主要有5个方法对象以上操作:
- save():
- update():
- delete():
- load():
- find():
(4)Transaction接口:
作用:底层封装JDBC,JTA,CORBA事务, 负责hibernate事务的管理。
(5)Query接口和Criteria接口:
作用:负责数据的查询
Query封装HQL(Hibernate Query Language)查询语句,Criteria封装基于字符串形式的查询语句
上述五大接口之间关系如下:
Hibernate的使用过程:
- 应用程序通过Configuration类读取配置文件并创建SessionFactory对象
- 通过SessionFactory对象生成一个Sesssion对象
- 通过Session对象的beginTrancation方法创建一个事务
- 通过Session对象的get()、load()、save()、update()、delete()、saveOrUpdate()方法实现数据的增删改
- 通过Session生成一个Query对象,利用Query对象执行查询操作
- 最后通过commit方法或者rollback方法完成事务操作
- 在完成所有持久化操作与事务操作后需关闭Session与SessionFactory
在使用Hibernate时如何提高性能?
延迟加载:当Hibernate从数据库中获取某个对象的值时通过建立代理对象把对象的属性设置为默认值,当使用这些
数据时才会从数据库中加载
缓存技术:Hibernate中提供了一级缓存和二级缓存。合理的利用缓存可以提高系统性能
优化查询语句:通过优化查询语句来提高系统性能
15、什么是Hibernate的二级缓存?
什么是缓存:
缓存的目的是为了通过减少应用程序对物理数据源访问的次数来提高程序运行的效率,原理是把当前或接下来一段时间
内可能会被用到的数据保存到内存中,在使用时直接从内存中读取,而不是从硬盘中读取
Hibernate中的缓存:
在Hibernate中,缓存用来把从数据库中查询出来的和使用过的对象保存到内存中,以便后期需要用到这个对象时可以直接
从缓存中获取这个对象,只有对象在缓存中不存在时才会去数据库中查询,缓存避免了大量发送SQL语句造成的性能损耗
另外Hibernate中的缓存分为一级缓存和二级缓存,一级缓存由Session管理,二级缓存由SessionFactory管理,一级缓存
必不可少,二级缓存可有可无
Hibernate中的一级缓存:
当用Session查询数据时,首先在该Session内部查找该对象是否存在,若存在直接返回,否则就到数据库中查询,并将
查询的结果缓存起来以便后期使用。一级缓存的缺点是当使用Session来表示一次会话时,它的生命周期较短,而且它是
线程不安全的,不能被多个线程共享,因此在实际使用中其对效率的提升不是很明显
Hibernate中的二级缓存:
二级缓存用来为Hibernate配置一种全局的缓存,以便实现多个线程与事务共享,在使用了二级缓存之后,当查询数据时会
首先在内部缓存中查找,如果不存在,接着在二级缓存中查找,最后才到数据库查找
另外二级缓存是独立于Hibernate的软件部件,属于第三方产品,常见的产品有EhCache、OSCache和JbossCache等
Hibernate3之后默认使用的产品是EhCache
16、Hibernate中session的update()和saveOrUpdate()、load()和get()有什么区别?
Hibernate的对象有3种状态,分别为:瞬时态(Transient)、持久态(Persistent)和脱管态(Detached)
saveOrUpdate方法(同时包含save方法和update方法的功能):
- 如果对象已经在本session中持久化了,不做任何操作,直接返回
- 如果传入的对象与session中另一个对象有相同的标识符,抛出一个异常
- 如果对象没有持久化标识(identifier)属性,对其调用save()
- 如果对象的持久标识(identifier)表明其是一个新实例化的对象,对其调用save()
- 如果对象是附带版本信息的(通过<version>或<timestamp>) 并且版本属性的值表明其是一个新实例化的对象,对其调用save()
- 否则update() 这个对象
get方法和load方法的区别:
- 如果数据库中不存在该对象,load方法抛出ObjectNotFoundException异常,而get方法返回null
- get方法首先查询Session内部缓存,若不存在接着查询二级缓存,最后查询数据库
- load方法首先查询Session内部缓存,若不存在创建代理对象,实际使用数据时再去查询二级缓存和数据库
- get方法永远返回实体类,load方法可以返回实体类的代理类实例
19、什么是SSH?
SSH:Structs + Spring + Hibernate
- 表示层(视图层):JSP
- 业务逻辑层:Spring
- 数据持久化层:Hibernate
补充:什么是SSM?
SSM:Spring+SpringMVC+MyBatis
框架原理:
页面发送请求给控制器,控制器调用业务层处理逻辑,逻辑层向持久层发送请求,持久层与数据库交互,后将结果返回给业务层,
业务层将处理逻辑发送给控制器,控制器再调用视图展现数据