* Spring 的优点有什么?
1. Spring 是分层的架构, 你可以选择使用你需要的层而不用管不需要的部分
2. Spring 是 POJO 编程, POJO 编程使得可持续构建和可测试能力提高
3. 依赖注入和 IoC 使得 JDBC 操作简单化
4. Spring 是开源的免费的
5. Spring 使得对象管理集中化合简单化
* 描述一下 spring 中实现 DI(dependency injection)的几种方式
方式一: 接口注入, 在实际中得到了普遍应用, 即使在 IoC 的概念尚未确立时, 这样的方法也已经频繁出现在我们的代码中.
方式二: Type2 IoC: Setter injection 对象创建之后, 将被依赖对象通过 set 方法设置进去
方式三: Type3 IoC: Constructor injection 对象创建时, 被依赖对象以构造方法参数的方式注入
Spring 的方式
* 简单描述下 IoC(inversion of control)的理解
一个类需要用到某个接口的方法, 我们需要将类 A 和接口 B 的实现关联起来, 最简单的方法是类 A 中创建一个对于接口 B 的实现 C 的实例, 但这种方法显然两者的依赖 (Dependency) 太大了. 而 IoC 的方法是只在类 A 中定义好用于关联接口 B 的实现的方法, 将类 A, 接口 B 和接口 B 的实现 C 放入 IoC 的 容器 (Container) 中, 通过一定的配置由容器 (Container) 来实现类 A 与接口 B 的实现 C 的关联.
* Spring 对很多 ORM 框架提供了很好支持, 描述下在 spring 使用 hibernate 的方法
在 context 中定义 DataSource, 创建 SessionFactoy, 设置参数; DAO 类继承 HibernateDaoSupport, 从中获得 HibernateTemplate 进行具体操作. 在使用中如果遇到 OpenSessionInView 的问题, 可以添加 OpenSessionInViewFilter 或 OpenSessionInViewInterceptor
* 请介绍下 spring 的事务管理
spring 提供了几个关于事务处理的类:
- TransactionDefinition // 事务属性定义
- TranscationStatus // 代表了当前的事务, 可以提交, 回滚.
PlatformTransactionManager 这个是 spring 提供的用于管理事务的基础接口, 其下有一个实现的抽象类 AbstractPlatformTransactionManager, 我们使用的事务管理类例如 DataSourceTransactionManager 等都是这个类的子类.
一般事务定义步骤:
- TransactionDefinition td = new TransactionDefinition();
- TransactionStatus ts = transactionManager.getTransaction(td);
- try
- {
- //do sth
- transactionManager.commit(ts);
- }
- catch(Exception e){
- transactionManager.rollback(ts);
- }
spring 提供的事务管理可以分为两类: 编程式的和声明式的. 编程式的, 比较灵活, 但是代码量大, 存在重复的代码比较多; 声明式的比编程式的更灵活.
编程式主要使用 transactionTemplate. 省略了部分的提交, 回滚, 一系列的事务对象定义, 需注入事务管理对象.
- void add()
- {
- transactionTemplate.execute( new TransactionCallback(){
- pulic Object doInTransaction(TransactionStatus ts)
- {
- //do sth
- }
- }
- }
声明式:
使用 TransactionProxyFactoryBean:
围绕 Poxy 的动态代理 能够自动的提交和回滚事务
org.springframework.transaction.interceptor.TransactionProxyFactoryBean
PROPAGATION_REQUIRED - 支持当前事务, 如果当前没有事务, 就新建一个事务. 这是最常见的选择.
PROPAGATION_SUPPORTS - 支持当前事务, 如果当前没有事务, 就以非事务方式执行.
PROPAGATION_MANDATORY - 支持当前事务, 如果当前没有事务, 就抛出异常.
PROPAGATION_REQUIRES_NEW - 新建事务, 如果当前存在事务, 把当前事务挂起.
PROPAGATION_NOT_SUPPORTED - 以非事务方式执行操作, 如果当前存在事务, 就把当前事务挂起.
PROPAGATION_NEVER - 以非事务方式执行, 如果当前存在事务, 则抛出异常.
PROPAGATION_NESTED - 如果当前存在事务, 则在嵌套事务内执行. 如果当前没有事务, 则进行与 PROPAGATION_REQUIRED 类似的操作.
* 如何在 spring 的 applicationContext.xml 使用 JNDI 而不是 DataSource
可以使用 "org.springframework.jndi.JndiObjectFactoryBean" 来实现. 示例如下:
- <bean id="dataSource">
- <property name="jndiName">
- <value>java:comp/env/jdbc/appfuse</value>
- </property>
- </bean>
* 在 spring 中是如何配置数据库驱动的
org.springframework.jdbc.datasource.DriverManagerDataSource" 数据源来配置数据库驱动. 示例如下:
- <bean id="dataSource">
- <property name="driverClassName">
- <value>org.hsqldb.jdbcDriver</value>
- </property>
- <property name="url">
- <value>jdbc:hsqldb:db/appfuse</value>
- </property>
- <property name="username"><value>sa</value></property>
- <property name="password"><value></value></property>
- </bean>
* spring 中的 applicationContext.xml 能不能改为其他名字
ContextLoaderListener 是一个 ServletContextListener, 它在你的 Web 应用启动的时候初始化. 缺省情况下, 它会在 Web-INF/applicationContext.xml 文件找 Spring 的配置. 你可以通过定义一个 < context-param > 元素名字为 "contextConfigLocation" 来改变 Spring 配置文件的位置. 示例如下:
- <listener>
- <listener-class>org.springframework.Web.context.ContextLoaderListener
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>/Web-INF/xyz.xml</param-value>
- </context-param>
- </listener-class>
- </listener>
* 在 Web 中如何配置 spring
在 J2EE 的 Web 应用里面配置 spring 非常简单, 最简单的只需要把 spring 得 ContextLoaderListener 添加到你的 Web.xml 文件里面就可以了, 示例如下:
- <listener>
- <listener-class>org.springframework.Web.context.ContextLoaderListener</listener-class>
- </listener>
* 在 spring 中如何定义 hibernate Mapping?
添加 hibernate mapping 文件到 Web/Web-INF 目录下的 applicationContext.xml 文件里面. 示例如下:
- <property name="mappingResources">
- <list>
- <value>org/appfuse/model/User.hbm.xml</value>
- </list>
- </property>
* 两种依赖注入的类型是什么?
两种依赖注入的类型分别是 setter 注入和构造方法注入.
setter 注入: 一般情况下所有的 java bean, 我们都会使用 setter 方法和 getter 方法去设置和获取属性的值, 示例如下:
- public class namebean {
- String name;
- public void setName(String a) {
- name = a; }
- public String getName() {
- return name; }
- }
我们会创建一个 bean 的实例然后设置属性的值, spring 的配置文件如下:
- <bean id="bean1″ >
- <property name="name" >
- <value>tom</value>
- </property>
- </bean>
Spring 会调用 setName 方法来只是 name 熟悉为 tom
构造方法注入: 构造方法注入中, 我们使用带参数的构造方法如下:
- public class namebean {
- String name;
- public namebean(String a) {
- name = a;
- }
- }
我们会在创建 bean 实例的时候以 new namebean("tom")的方式来设置 name 属性, Spring 配置文件如下:
- <bean id="bean1″ >
- <constructor-arg>
- <value>My Bean Value</value>
- </constructor-arg>
- </bean>
使用 constructor-arg 标签来设置构造方法的参数.
* 解释一下 Dependency Injection(DI)和 IoC(inversion of control)?
参考答案: 依赖注入 DI 是一个程序设计模式和架构模型, 一些时候也称作控制反转, 尽管在技术上来讲, 依赖注入是一个 IoC 的特殊实现, 依赖注入是指一个对象应用另外一个对象来提供一个特殊的能力, 例如: 把一个数据库连接已参数的形式传到一个对象的结构方法里面而不是在那个对象内部自行创建一个连接. 控制反转和依赖注入的基本思想就是把类的依赖从类内部转化到外部以减少依赖
应用控制反转, 对象在被创建的时候, 由一个调控系统内所有对象的外界实体, 将其所依赖的对象的引用, 传递给它. 也可以说, 依赖被注入到对象中. 所以, 控制反转是, 关于一个对象如何获取他所依赖的对象的引用, 这个责任的反转
* Spring 中 BeanFactory 和 ApplicationContext 的作用和区别
作用:
1. BeanFactory 负责读取 bean 配置文档, 管理 bean 的加载, 实例化, 维护 bean 之间的依赖关系, 负责 bean 的声明周期.
2. ApplicationContext 除了提供上述 BeanFactory 所能提供的功能之外, 还提供了更完整的框架功能:
a. 国际化支持
b. 资源访问: Resource rs = ctx. getResource("classpath:config.properties"), "file:c:/config.properties"
c. 事件传递: 通过实现 ApplicationContextAware 接口
3. 常用的获取 ApplicationContext 的方法:
FileSystemXmlApplicationContext: 从文件系统或者 url 指定的 xml 配置文件创建, 参数为配置文件名或文件名数组
ClassPathXmlApplicationContext: 从 classpath 的 xml 配置文件创建, 可以从 jar 包中读取配置文件
WebApplicationContextUtils: 从 Web 应用的根目录读取配置文件, 需要先在 Web.xml 中配置, 可以配置监听器或者 servlet 来实现
- <listener>
- <listener-class>
- org.springframework.Web.context.ContextLoaderListener
- </listener-class>
- </listener>
- <servlet>
- <servlet-name>
- context
- </servlet-name>
- <servlet-class>
- org.springframework.Web.context.ContextLoaderServlet
- </servlet-class>
- <load-on-startup>
- 1
- </load-on-startup>
- </servlet>
这两种方式都默认配置文件为 Web-inf/applicationContext.xml, 也可使用 context-param 指定配置文件
- <context-param>
- <param-name>
- contextConfigLocation
- </param-name>
- <param-value>
- /Web-INF/myApplicationContext.xml
- </param-value>
- </context-param>
* 在 Web 环境下如何配置 applicationContext.xml 文件
- <listener>
- <listener-class>
- org.springframework.Web.context.ContextLoaderListener
- </listener-class>
- </listener>
或:
- <servlet>
- <servlet-name>context</servlet-name>
- <servlet-class>
- org.springframework.Web.context.ContextLoaderServlet
- </servlet-class>
- <load-on-startup>1</load-on-startup>
- </servlet>
通过如下方法取出 applicationContext 实例:
ApplicationContext ac=WebApplicationContextUtils.getWebApplicationContext(this.getServletContext);
* 如何配置 spring + struts?
在 struts-config.xml 加入一个插件, 通过它加载 applicationContext.xml
在 struts-config.xml 修改 action-mapping 标记, 具体 action 交给了 DelegateActionProxy?
通过 DelegateActionProxy 进入一 spring 的环境.?
在 spring 的 applicationContext.xml 加入?<bean name="/login" class=""singleton="false"/>
* Spring 和 hibernate 的配置文件中的主要类型有哪些? 如何配置?
在 myeclipse 中先加入 spring 环境再加入 hibernate 环境.
如果 spring 与 hibernate 结合在一起可以不需要 hibernate.cfg.xml 文件是否正确?
spring+hibernate 的配置文件中的主要类有那些? 如何配置?
dataSource
sessionFactory:hibernate.cfg.xml
- transactionManager
- userDao (extends HibernateDaoSupport)
- sessionFactory
- facade
- proxy
- sessionFactory
- transactionManager
- facade
* 在 spring 中如何配置容器的事物管理, 相关的类有哪些?
- Datasouce
- transactionManager
userDao 要注入
Datasouce
Proxy 代理
Target:userDao: 代理对象(目标对象)
- transactionAttributes(那些方法需要事务处理)
- transactionManager(事务处理服务)
* 在 spring 中如何配代码的事务管理器
- Datasouce
- transactionManager
userDao 要注入
- Datasouce
- transactionManager
通过如下类实现
- TransactionTemplate
- JdbcTemplate
* Spring 中有几种事物管理, 分别是什么?
代码管理的事务处理
TransactonTemplate 的 execute 方法中的内部类 TransactionCallback 中的 doInTransaction 方法中使用.
- public void make()
- {
- TransactionTemplate jtm=new TransactionTemplate(this.getTransactionManager());
- jtm.execute(new myClass1());
- }
- public class myClass1 implements TransactionCallback
- {
- public Object doInTransaction(TransactionStatus trans)
- {
- JdbcTemplate jdbc=new JdbcTemplate(dataSource);
- jdbc.execute("insert into customer(customerName) values('b')");
- jdbc.execute("insert into customer(customerName) values('b')");
- return null;
- }
- }
容器管理的事务处理
* spring 中的 jdbc 与传统的 jdbc 有什么区别?
Spring 的 jdbc: 节省代码, 不管连接(Connection), 不管事务, 不管异常, 不管关闭(con.close() ps.close )
JdbcTemplate(dataSource): 增, 删, 改, 查
TransactionTemplate(transactionManager): 进行事务处理
* Spring 配置的主要标签有什么? 有什么作用?
- <beans>
- <bean id=""class="" init=""destroy="" singleton="">
- <property name="">
- <value></value>
- </property>
- <property name="">
- <ref local></ref>
- </property>
- </bean>
- </beans>
* 如何在 spring 中实现国际化?
在 applicationContext.xml 加载一个 bean
- <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
- <property name="basename">
- <value>message</value>
- </property>
- </bean>
在 src 目录下建多个 properties 文件?
对于非英文的要用 native2ascii? -encoding gb2312 源 目转化文件相关内容
其命名格式是 message_语言_国家.?
页面中的中显示提示信息, 键名取键值.?
当给定国家, 系统会自动加载对应的国家的 properties 信息.?
通过 applictionContext.getMessage("键名","参数","区域")取出相关的信息.?
* 在 spring 中如何实现事件处理
事件
Extends ApplicationEvent
监听器
Implements ApplicationListener
事件源
Implements ApplicationContextAware
在 applicationContext.xml 中配置事件源, 监听器
先得到事件源, 调用事件源的方法, 通知监听器.
* 如何将 spring 加入 Web 容器中
在 Web.xml 中加入如下同容, 在启动 Web 服务器时加载 / Web-INF/applicationContext.xml 中的内容.
- <servlet>
- <servlet-name>
- context
- </servlet-name>
- <servlet-class>
- org.springframework.Web.context.ContextLoaderServlet
- </servlet-class>
- <load-on-startup>
- 1
- </load-on-startup>
- </servlet>
通过如下类得到 ApplicationContext 实例
WebApplicationContextUtils.getWebApplicationContext
* Spring 如何实现资源管理?
使用
applicationContext.getResource("classpath: 文件名"): 在 src 根目录下, 在类路径下
applicationContext.getResource("classpath:/chap01 / 文件名"): 以 src 根目录下的基准往下走.
applicationContext.getResource("file:c:/a.properties"): 在系统文件目录下.
* Spring 的 ApplicationContext 的作用?
beanFactory
国际化(getMesage)
资源管理: 可以直接读取一个文件的内容(getResource)
加入 Web 框架中(加入一个 servlet 或监听器)
事件处理
* spring 的核心是什么, 各有什么作用?
BeanFactory: 产生一个新的实例, 可以实现单例模式
BeanWrapper: 提供统一的 get 及 set 方法
ApplicationContext: 提供框架的实现, 包括 BeanFactory 的所有功能
* Spring 中 aop 的关键名词有哪些? 各有什么作用?
拦截器: 代理
装备(advice)
目标对象
关切点: 条件
连接点: 方法, 属性
* Spring 与 struts 的区别?
strusts: 是一种基于 MVC 模式的一个 Web 层的处理.
Spring: 提供了通用的服务, IoC/di aop, 关心的不仅仅 Web 层, 应当 j2ee 整体的一个服务, 可以很容易融合不同的技术 struts hibernate ibatis ejb remote springJDBC springMVC
* spring 与 struts 的面试题
1.struts
Action 是不是线程安全的? 如果不是, 有什么方式可以保证 Action 的线程安全? 如果是, 说明原因
2.MVC, 分析一下 struts 是如何实现 MVC 的
3.struts 中的几个关键对象的作用(说说几个关键对象的作用)
4.spring
说说 AOP 和 IoC 的概念以及在 spring 中是如何应用的
5.Hibernate 有哪几种查询数据的方式
6.load()和 get()的区别
回答:
1.Struts1 Action 是单例模式并且必须是线程安全的, 因为仅有 Action 的一个实例来处理所有的请求. 单例策略限制了 Struts1 Action 能作的事, 并且要在开发时特别小心. Action 资源必须是线程安全的或同步的.
Struts2 Action 对象为每一个请求产生一个实例, 因此没有线程安全问题.(实际上, servlet 容器给每个请求产生许多可丢弃的对象, 并且不会导致性能和垃圾回收问题)
2.struts 是用一组类, servlet 和 jsp 规范实现 mvc 的
3.ActionFrom ActionServlet Action struts-config.xml
4.spring 的核心就是 IoC, 通过指定对象的创建办法, 描述对象与服务之间的关系, 而不生成对象
5.3 种, hql 条件查询() 原生 sql
6.load()方法认为该数据一定存在, 可以放心的使用代理来延时加载 , 如果使用过程中发现了问题, 就抛出异常;
get()方法一定要获取到真实的数据, 否则返回 null
* Spring, hibernate ,struts 面试题
Hibernate 工作原理及为什么要用?
原理:
1. 读取并解析配置文件
2. 读取并解析映射信息, 创建 SessionFactory
3. 打开 Sesssion
4. 创建事务 Transation
5. 持久化操作
6. 提交事务
7. 关闭 Session
8. 关闭 SesstionFactory
为什么要用:
* 对 JDBC 访问数据库的代码做了封装, 大大简化了数据访问层繁琐的重复性代码.
* Hibernate 是一个基于 JDBC 的主流持久化框架, 是一个优秀的 ORM 实现. 他很大程度的简化 DAO 层的编码工作
* hibernate 使用 Java 反射机制, 而不是字节码增强程序来实现透明性.
* hibernate 的性能非常好, 因为它是个轻量级框架. 映射的灵活性很出色. 它支持各种关系数据库, 从一对一到多对多的各种复杂关系.
Hibernate 是如何延迟加载?
* Hibernate2 延迟加载实现: a)实体对象 b)集合(Collection)
* Hibernate3 提供了属性的延迟加载功能
当 Hibernate 在查询数据的时候, 数据并没有存在与内存中, 当程序真正对数据的操作时, 对象才存在与内存中, 就实现了延迟加载, 他节省了服务器的内存开销, 从而提高了服务器的性能.
Hibernate 中怎样实现类之间的关系?(如: 一对多, 多对多的关系)
类与类之间的关系主要体现在表与表之间的关系进行操作, 它们都市对对象进行操作, 我们程序中把所有的表与类都映射在一起, 它们通过配置文件中的 many-to-one,one-to-many,many-to-many,
说下 Hibernate 的缓存机制
* 内部缓存存在 Hibernate 中又叫一级缓存, 属于应用事物级缓存
* 二级缓存:
a)应用及缓存
b)分布式缓存
条件: 数据不会被第三方修改, 数据大小在可接受范围, 数据更新频率低, 同一数据被系统频繁使用, 非 关键数据
c) 第三方缓存的实现
Hibernate 的查询方式
- Sql,Criteria,object comptosition
- Hql:
* 属性查询
* 参数查询, 命名参数查询
* 关联查询
* 分页查询
* 统计函数
如何优化 Hibernate?
* 使用双向一对多关联, 不使用单向一对多
* 灵活使用单向一对多关联
* 不用一对一, 用多对一取代
* 配置对象缓存, 不使用集合缓存
* 一对多集合使用 Bag, 多对多集合使用 Set
* 继承类使用显式多态
* 表字段要少, 表关联不要怕多, 有二级缓存撑腰
Struts 工作机制? 为什么要使用 Struts?
工作机制:
Struts 的工作流程:
在 Web 应用启动时就会加载初始化 ActionServlet,ActionServlet 从 struts-config.xml 文件中读取配置信息, 把它们存放到各种配置对象当 ActionServlet 接收到一个客户请求时, 将执行如下流程.
(1)检索和用户请求匹配的 ActionMapping 实例, 如果不存在, 就返回请求路径无效信息;
(2)如果 ActionForm 实例不存在, 就创建一个 ActionForm 对象, 把客户提交的表单数据保存到 ActionForm 对象中;
(3)根据配置信息决定是否需要表单验证. 如果需要验证, 就调用 ActionForm 的 validate()方法;
(4)如果 ActionForm 的 validate()方法返回 null 或返回一个不包含 ActionMessage 的 ActuibErrors 对象, 就表示表单验证成功;
(5)ActionServlet 根据 ActionMapping 所包含的映射信息决定将请求转发给哪个 Action, 如果相应的 Action 实例不存在, 就先创建这个实例, 然后调用 Action 的 execute()方法;
(6)Action 的 execute()方法返回一个 ActionForward 对象, ActionServlet 在把客户请求转发给 ActionForward 对象指向的 JSP 组件;
(7)ActionForward 对象指向 JSP 组件生成动态网页, 返回给客户;
为什么要用:
JSP,Servlet,JavaBean 技术的出现给我们构建强大的企业应用系统提供了可能. 但用这些技术构建的系统非常的繁乱, 所以在此之上, 我们需要一个规则, 一个把这些技术组织起来的规则, 这就是框架, Struts 便应运而生.
基于 Struts 开发的应用由 3 类组件构成: 控制器组件, 模型组件, 视图组件
Struts 的 validate 框架是如何验证的?
在 struts 配置文件中配置具体的错误提示, 再在 FormBean 中的 validate()方法具体调用.
说下 Struts 的设计模式
MVC 模式: Web 应用程序启动时就会加载并初始化 ActionServler. 用户提交表单时, 一个配置好的 ActionForm 对象被创建, 并被填入表单相应的数据, ActionServler 根据 Struts-config.xml 文件配置好的设置决定是否需要表单验证, 如果需要就调用 ActionForm 的 Validate()验证后选择将请求发送到哪个 Action, 如果 Action 不存在, ActionServlet 会先创建这个对象, 然后调用 Action 的 execute()方法. Execute()从 ActionForm 对象中获取数据, 完成业务逻辑, 返回一个 ActionForward 对象, ActionServlet 再把客户请求转发给 ActionForward 对象指定的 jsp 组件, ActionForward 对象指定的 jsp 生成动态的网页, 返回给客户.
单例模式
Factory(工厂模式):
定义一个基类 ===》实现基类方法(子类通过不同的方法)===》定义一个工厂类(生成子类实例)
===》开发人员调用基类方法
Proxy(代理模式)
spring 工作机制及为什么要用?
1.spring mvc 请所有的请求都提交给 DispatcherServlet, 它会委托应用系统的其他模块负责负责对请求进行真正的处理工作.
2.DispatcherServlet 查询一个或多个 HandlerMapping, 找到处理请求的 Controller.
3.DispatcherServlet 请请求提交到目标 Controller
4.Controller 进行业务逻辑处理后, 会返回一个 ModelAndView
5.Dispathcher 查询一个或多个 ViewResolver 视图解析器, 找到 ModelAndView 对象指定的视图对象
6. 视图对象负责渲染返回给客户端.
为什么用:
AOP 让开发人员可以创建非行为性的关注点, 称为横切关注点, 并将它们插入到应用程序代码中. 使用 AOP 后, 公共服务 (比 如日志, 持久性, 事务等)就可以分解成方面并应用到域对象上, 同时不会增加域对象的对象模型的复杂性.
IoC 允许创建一个可以构造对象的应用环境, 然后向这些对象传递它们的协作对象. 正如单词 倒置 所表明的, IoC 就像反 过来的 JNDI. 没有使用一堆抽象工厂, 服务定位器, 单元素 (singleton) 和直接构造(straight construction), 每一个对象都是用 其协作对象构造的. 因此是由容器管理协作对象(collaborator).
Spring 即使一个 AOP 框架, 也是一 IoC 容器. Spring 最好的地方是它有助于您替换对象. 有了 Spring, 只要用 JavaBean 属性和配置文件加入依赖性(协作对象). 然后可以很容易地在需要时替换具有类似接口的协作对象.
* 一些 spring 与 hibernate 的面试题
1, 简述你对 IoC(Inversion of Control)的理解, 描述一下 Spring 中实现 DI(Dependency Injection)的几种方式.
2, Spring 的 Bean 有多种作用域, 包括:
singleton,prototype,request,session,global session,application, 自定义
3, 简单描述 Spring framework 与 Struts 的不同之处, 整合 Spring 与 Struts 有哪些方法, 哪种最好, 为什么?
4, Hibernate 中的 update()和 saveOrUpdate()的区别
5, Spring 对多种 ORM 框架提供了很好的支持, 简单描述在 Spring 中使用 Hibernate 的方法, 并结合事务管理.
答案:
1, 好莱坞原则€€€€不要打电话找我, 我会打给你的. IoC 将创建的职责从应用程序代码搬到了框架中. Spring 对 Setter 注入和构造方法注入提供支持.(详见 http://martinfowler.com/articles/injection.html, 以及 http: //www.redsaga.com/spring_ref/2.0/HTML/beans.HTML#beans-factory- collaborators)
2, 除 application(详见 Spring framework 2.0 Reference 的 3.4 节 bean 的作用域)
3, Spring 是完整的一站式框架, 而 Struts 仅是 MVC 框架, 且着重于 MVC 中的 C.Spring 有三种方式整合 Struts: 使用 Spring 的 ActionSupport 类整合 Struts; 使用 Spring 的 DelegatingRequestProcessor 覆盖 Struts 的 RequestProcessor; 将 Struts Action 管理委托给 Spring 框架, 动作委托最好.(详见使用 Spring 更好地处理 Struts 动作)
Spring 2.0 新增一种方式: AutowiringRequestProcessor.(详见 http://www.javaeye.com/topic/24239)
4, saveOrUpdate()方法可以实现 update()的功能, 但会多些步骤, 具体如下:
如果对象在该 session 中已经被持久化, 不进行操作;
对象的标识符属性 (identifier property) 在数据库中不存在或者是个暂时的值, 调用 save()方法保存它;
如果 session 中的另一个对象有相同的标识符抛出一个异常;
以上皆不符合则调用 update()更新之.
5, 在 context 中定义 DataSource, 创建 SessionFactoy, 设置参数; DAO 类继承 HibernateDaoSupport, 实现具体接口, 从中获得 HibernateTemplate 进行具体操作.
在使用中如果遇到 OpenSessionInView 的问题, 可以添加 OpenSessionInViewFilter 或 OpenSessionInViewInterceptor.(详见 Spring framework 2.0 Reference 的 12.2 节 Hibernate)
声明式事务需声明事务管理器, 在 context 中设置指定属性, 用确定和.
* 在 spring 中如何更加高效的使用 JDBC
使用 Spring 框架提供的模板类 JdbcTemplete 可以是 JDBC 更加高效
代码如下: JdbcTemplate template = new JdbcTemplate(myDataSource);
DAO 类的例子:
- public class StudentDaoJdbc implements StudentDao {
- private JdbcTemplate jdbcTemplate;
- public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
- this.jdbcTemplate = jdbcTemplate;
- }
- more..
- }
配置文件:
- <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
- <property name="dataSource">
- <ref bean="dataSource" />
- </property>
- </bean>
- <bean id="studentDao" class="StudentDaoJdbc">
- <property name="jdbcTemplate">
- <ref bean="jdbcTemplate" />
- </property>
- </bean>
- <bean id="courseDao" class="CourseDaoJdbc">
- <property name="jdbcTemplate">
- <ref bean="jdbcTemplate" />
- </property>
- </bean>
* 在 spring 如何创建一个数据连接池
- <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
- <property name="driver">
- <value>
- ${db.driver}
- </value>
- </property>
- <property name="url">
- <value>
- ${db.url}
- </value>
- </property>
- <property name="username">
- <value>
- ${db.username}
- </value>
- </property>
- <property name="password">
- <value>
- ${db.password}
- </value>
- </property>
- </bean>
* 在 spring 中如何配置一个 bean 来从 JNDI 到 dataSource
- <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
- <property name="jndiName">
- <value>
- java:comp/env/jdbc/myDatasource
- </value>
- </property>
- </bean>
* 请介绍下 spring 中 bean 的作用域
在 spring2.0 之前 bean 只有 2 种作用域即: singleton(单例),non-singleton(也称 prototype),Spring2.0 以后, 增加了 session,request,global session 三种专用于 Web 应用程序上下文的 Bean. 因此, 默认情况下 Spring2.0 现在有五种类型的 Bean.
<bean id="role" class="spring.chapter2.maryGame.Role" scope="singleton"/>
这里的 scope 就是用来配置 spring bean 的作用域, 它标识 bean 的作用域.
在 spring2.0 之前 bean 只有 2 种作用域即: singleton(单例),non-singleton(也称 prototype),Spring2.0 以后, 增加了 session,request,global session 三种专用于 Web 应用程序上下文的 Bean. 因此, 默认情况下 Spring2.0 现在有五种类型的 Bean. 当然, Spring2.0 对 Bean 的类型的设计进行了重构, 并设计出灵活的 Bean 类型支持, 理论上可以有无数多种类型的 Bean, 用户可以根据自己的需要, 增加新的 Bean 类型, 满足实际应用需求.
1,singleton 作用域
当一个 bean 的作用域设置为 singleton, 那么 Spring IoC 容器中只会存在一个共享的 bean 实例, 并且所有对 bean 的请求, 只要 id 与该 bean 定义相匹配, 则只会返回 bean 的同一实例. 换言之, 当把一个 bean 定义设置为 singleton 作用域时, Spring IoC 容器只会创建该 bean 定义的唯一实例. 这个单一实例会被存储到单例缓存 (singleton cache) 中, 并且所有针对该 bean 的后续请求和引用都将返回被缓存的对象实例, 这里要注意的是 singleton 作用域和 GOF 设计模式中的单例是完全不同的, 单例设计模式表示一个 ClassLoader 中只有一个 class 存在, 而这里的 singleton 则表示一个容器对应一个 bean, 也就是说当一个 bean 被标识为 singleton 时候, spring 的 IoC 容器中只会存在一个该 bean.
配置实例:
<bean id="role" class="spring.chapter2.maryGame.Role" scope="singleton"/>
或者
- <bean id="role" class="spring.chapter2.maryGame.Role" singleton="true"
- />
- 2,prototype
prototype 作用域部署的 bean, 每一次请求 (将其注入到另一个 bean 中, 或者以程序的方式调用容器的 getBean() 方法)都会产生一个新的 bean 实例, 相当于一个 new 的操作, 对于 prototype 作用域的 bean, 有一点非常重要, 那就是 Spring 不能对一个 prototype bean 的整个生命周期负责, 容器在初始化, 配置, 装饰或者是装配完一个 prototype 实例后, 将它交给客户端, 随后就对该 prototype 实例不闻不问了. 不管何种作用域, 容器都会调用所有对象的初始化生命周期回调方法, 而对 prototype 而言, 任何配置好的析构生命周期回调方法都将不会被调用. 清除 prototype 作用域的对象并释放任何 prototype bean 所持有的昂贵资源, 都是客户端代码的职责.(让 Spring 容器释放被 singleton 作用域 bean 占用资源的一种可行方式是, 通过使用 bean 的后置处理器, 该处理器持有要被清除的 bean 的引用.)
配置实例:
<bean id="role" class="spring.chapter2.maryGame.Role" scope="prototype"/>
或者
- <beanid="role" class="spring.chapter2.maryGame.Role" singleton="false"
- />
- 3,request
request 表示该针对每一次 HTTP 请求都会产生一个新的 bean, 同时该 bean 仅在当前 HTTP request 内有效, 配置实例:
request,session,global session 使用的时候, 首先要在初始化 Web 的 Web.xml 中做如下配置:
如果你使用的是 Servlet 2.4 及以上的 Web 容器, 那么你仅需要在 Web 应用的 xml 声明文件 Web.xml 中增加下述 ContextListener 即可:
- <Web-App>
- ...
- <listener>
- <listener-class>
- org.springframework.Web.context.request.RequestContextListener
- </listener-class>
- </listener>
- ...
- </Web-App>
如果是 Servlet2.4 以前的 Web 容器, 那么你要使用一个 javax.servlet.Filter 的实现:
- <Web-App>
- ..
- <filter>
- <filter-name>
- requestContextFilter
- </filter-name>
- <filter-class>
- org.springframework.Web.filter.RequestContextFilter
- </filter-class>
- </filter>
- <filter-mapping>
- <filter-name>
- requestContextFilter
- </filter-name>
- <url-pattern>
- /*
- </url-pattern>
- </filter-mapping>
- ...
- </Web-App>
接着既可以配置 bean 的作用域了:
- <bean id="role" class="spring.chapter2.maryGame.Role" scope="request"
- />
- 4,session
session 作用域表示该针对每一次 HTTP 请求都会产生一个新的 bean, 同时该 bean 仅在当前 HTTP session 内有效, 配置实例:
配置实例:
和 request 配置实例的前提一样, 配置好 Web 启动文件就可以如下配置:
- <bean id="role" class="spring.chapter2.maryGame.Role" scope="session"
- />
- 5,global session
global session 作用域类似于标准的 HTTP Session 作用域, 不过它仅仅在基于 portlet 的 Web 应用中才有意义. Portlet 规范定义了全局 Session 的概念, 它被所有构成某个 portlet Web 应用的各种不同的 portlet 所共享. 在 global session 作用域中定义的 bean 被限定于全局 portlet Session 的生命周期范围内. 如果你在 Web 中使用 global session 作用域来标识 bean, 那么, Web 会自动当成 session 类型来使用.
配置实例:
和 request 配置实例的前提一样, 配置好 Web 启动文件就可以如下配置:
<bean id="role" class="spring.chapter2.maryGame.Role" scope="global session"/>
6, 自定义 bean 装配作用域
在 spring 2.0 中作用域是可以任意扩展的, 你可以自定义作用域, 甚至你也可以重新定义已有的作用域(但是你不能覆盖 singleton 和 prototype),spring 的作用域由接口 org.springframework.beans.factory.config.Scope 来定义, 自定义自己的作用域只要实现该接口即可, 下面给个实例:
我们建立一个线程的 scope, 该 scope 在表示一个线程中有效, 代码如下:
- publicclass MyScope implements Scope ...{
- privatefinal ThreadLocal threadScope = new ThreadLocal() ...{
- protected Object initialValue() ...{
- returnnew HashMap();
- }
- };
- public Object get(String name, ObjectFactory objectFactory) ...{
- Map scope = (Map) threadScope.get();
- Object object = scope.get(name);
- if(object==null) ...{
- object = objectFactory.getObject();
- scope.put(name, object);
- }
- return object;
- }
- public Object remove(String name) ...{
- Map scope = (Map) threadScope.get();
- return scope.remove(name);
- }
- publicvoid registerDestructionCallback(String name, Runnable callback) ...{
- }
- public String getConversationId() ...{
- // TODO Auto-generated method stub
- returnnull;
- }
- }
* 请介绍 一下 spring 的 bean 的生命周期
一, Bean 的定义
Spring 通常通过配置文件定义 Bean. 如:
- <?xml version="1.0″ encoding="UTF-8″?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
- <bean id="HelloWorld" class="com.pqf.beans.HelloWorld">
- <property name="msg">
- <value>HelloWorld</value>
- </property>
- </bean>
- </beans>
这个配置文件就定义了一个标识为 HelloWorld 的 Bean. 在一个配置文档中可以定义多个 Bean.
二, Bean 的初始化
有两种方式初始化 Bean.
1, 在配置文档中通过指定 init-method 属性来完成
在 Bean 的类中实现一个初始化 Bean 属性的方法, 如 init(), 如:
- public class HelloWorld{
- public String msg=null;
- public Date date=null;
- public void init() {
- msg="HelloWorld";
- date=new Date();
- }
- ......
- }
然后, 在配置文件中设置 init-mothod 属性:
- <bean id="HelloWorld" class="com.pqf.beans.HelloWorld" init-mothod="init">
- </bean>
2, 实现 org.springframwork.beans.factory.InitializingBean 接口
Bean 实现 InitializingBean 接口, 并且增加 afterPropertiesSet() 方法:
- public class HelloWorld implement InitializingBean {
- public String msg=null;
- public Date date=null;
- public void afterPropertiesSet() {
- msg="向全世界问好!";
- date=new Date();
- }
- ......
- }
那么, 当这个 Bean 的所有属性被 Spring 的 BeanFactory 设置完后, 会自动调用 afterPropertiesSet()方法对 Bean 进行初始化, 于是, 配置文件就不用指定 init-method 属性了.
三, Bean 的调用
有三种方式可以得到 Bean 并进行调用:
1, 使用 BeanWrapper
- HelloWorld hw=new HelloWorld();
- BeanWrapper bw=new BeanWrapperImpl(hw);
- bw.setPropertyvalue("msg","HelloWorld");
- system.out.println(bw.getPropertyCalue("msg"));
2, 使用 BeanFactory
- InputStream is=new FileInputStream("config.xml");
- XmlBeanFactory factory=new XmlBeanFactory(is);
- HelloWorld hw=(HelloWorld) factory.getBean("HelloWorld");
- system.out.println(hw.getMsg());
3, 使用 ApplicationConttext
- ApplicationContext actx=new FleSystemXmlApplicationContext("config.xml");
- HelloWorld hw=(HelloWorld) actx.getBean("HelloWorld");
- System.out.println(hw.getMsg());
四, Bean 的销毁
1, 使用配置文件中的 destory-method 属性
与初始化属性 init-methods 类似, 在 Bean 的类中实现一个撤销 Bean 的方法, 然后在配置文件中通过 destory-method 指定, 那么当 bean 销毁时, Spring 将自动调用指定的销毁方法.
2, 实现 org.springframwork.bean.factory.DisposebleBean 接口
如果实现了 DisposebleBean 接口, 那么 Spring 将自动调用 bean 中的 Destory 方法进行销毁, 所以, Bean 中必须提供 Destory 方法.
* Spring 中如何获取 bean
通过 xml 配置文件
bean 配置在 xml 里面, spring 提供多种方式读取配置文件得到 ApplicationContext.
第一种方式: FileSystemXmlApplicationContext
通过程序在初始化的时候, 导入 Bean 配置文件, 然后得到 Bean 实例:
- ApplicationContext ac = new FileSystemXmlApplicationContext("applicationContext.xml")
- ac.getBean("beanName");
第二种方式: WebApplicationContextUtil
在 B/S 系统中, 通常在 Web.xml 初始化 bean 的配置文件, 然后由 WebAppliCationContextUtil 得到 ApplicationContext. 例如:
- ApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(ServletContext sc);
- ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(ServletContext sc);
其中 servletContext sc 可以具体 换成 servlet.getServletContext()或者 this.getServletContext() 或者 request.getSession().getServletContext();
另外, 由于 spring 是注入的对象放在 ServletContext 中的, 所以可以直接在 ServletContext 取出 WebApplicationContext 对象:
WebApplicationContext webApplicationContext = (WebApplicationContext) servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
* Spring 框架有哪几部分组成?
Spring 框架有七个模块组成组成, 这 7 个模块 (或组件) 均可以单独存在, 也可以与其它一个或多个模块联合使用, 主要功能表现如下:
1 Spring 核心容器 (Core): 提供 Spring 框架的基本功能. 核心容器的主要组件是 BeanFactory, 她是工厂模式的实现. BeanFactory 使用控制反转(IoC) 模式将应用程序的配置和依赖性规范与实际的应用代码程序分开.
2 Spring AOP: 通过配置管理特性, Spring AOP 模块直接面向方面的编程功能集成到了 Spring 框架中, 所以可以很容易的使 Spring 框架管理的任何对象支持 AOP.Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务. 通过使用 Spring AOP, 不用依赖于 EJB 组件, 就可以将声明性事务管理集成到应用程序中.
3 Spring ORM:Spring 框架集成了若干 ORM 框架, 从而提供了 ORM 的对象关系工具, 其中包括 JDO,Hibernate,iBatis 和 TopLink. 所有这些都遵从 Spring 的通用事务和 DAO 异常层结构.
4 Spring DAO:JDBC DAO 抽象层提供了有意义的异常层次的结构, 可用该结构来管理异常处理和不同数据供应商抛出的异常错误信息. 异常层次结构简化了错误处理, 并且大大的降低 了需要编写的异常代码数量(例如, 打开和关系连接).Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层结构.
5 Spring Web:Web 上下文模块建立在上下文模块 (Context) 的基础之上, 为基于 Web 服务的应用程序提供了上下文的服务. 所以 Spring 框架支持 Jakarta Struts 的集成. Web 模块还简化了处理多部分请求及将请求参数绑定到域对象的工作.
6 Spring 上下文(Context):Spring 上下文是一个配置文件, 向 Spring 框架提供上下文信息. Spring 上下文包括企业服务, 例如 JNDI,EJB, 电子邮件, 国际化校验和调度功能.
7 Spring MVC:Spring 的 MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现. 通过策略接口, MVC 框架变成为高度可配置的, MVC 容纳的大量视图技术, 包括 JSP,Velocity,Tiles,iText 和 Pol
* 使用 spring 有什么好处?
◆Spring 能有效地组织你的中间层对象, 无论你是否选择使用了 EJB. 如果你仅仅使用了 Struts 或其他的包含了 J2EE 特有 APIs 的 framework, 你会发现 Spring 关注了遗留下的问题,.
◆Spring 能消除在许多工程上对 Singleton 的过多使用. 根据我的经验, 这是一个主要的问题, 它减少了系统的可测试性和面向对象特性.
◆Spring 能消除使用各种各样格式的属性定制文件的需要, 在整个应用和工程中, 可通过一种 一致的方法来进行配置. 曾经感到迷惑, 一个特定类要查找迷幻般的属性关键字或系统属性, 为此不得不读 Javadoc 乃至源编码吗? 有了 Spring, 你可 很简单地看到类的 JavaBean 属性. 倒置控制的使用 (在下面讨论) 帮助完成这种简化.
◆Spring 能通过接口而不是类促进好的编程习惯, 减少编程代价到几乎为零.
◆Spring 被设计为让使用它创建的应用尽可能少的依赖于他的 APIs. 在 Spring 应用中的大多数业务对象没有依赖于 Spring.
◆使用 Spring 构建的应用程序易于单元测试.
◆Spring 能使 EJB 的使用成为一个实现选择, 而不是应用架构的必然选择. 你能选择用 POJOs 或 local EJBs 来实现业务接口, 却不会影响调用代码.
◆Spring 帮助你解决许多问题而无需使用 EJB.Spring 能提供一种 EJB 的替换物, 它们适于许多 Web 应用. 例如, Spring 能使用 AOP 提供声明性事务而不通过使用 EJB 容器, 如果你仅仅需要与单个的数据库打交道, 甚至不需要 JTA 实现.
■Spring 为数据存取提供了一致的框架, 不论是使用 JDBC 或 O/R mapping 产品(如 Hibernate).
Spring 确实使你能通过最简单可行的解决办法解决你的问题. 这些特性是有很大价值的.
总结起来, Spring 有如下优点:
◆低侵入式设计, 代码污染极低
◆ 独立于各种应用服务器, 可以真正实现 Write Once,Run Anywhere 的承诺
◆Spring 的 DI 机制降低了业务对象替换的复杂性
◆Spring 并不完全依赖于 Spring, 开发者可自由选用 Spring 框架的部分或全部
* 什么是 spring, 它有什么特点?
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 也提供了很多基础功能(事务管理, 持久化框架集成等等), 将应用逻辑的开发留给了你.
---------------------