Spring中,BeanFactory提供了一种先进的配置机制来管理任何种类bean(对象),
ApplicationContext是BeanFactory的完全超集,我们大部分时间面对的是ApplicationContext,通过它取得bean,处理bean,而其他的事务管理、远程访问等则交由Spring容器去管理好了。很多情况下,用户代码不需要实例化BeanFactory,
因为Spring框架代码会做这件事。例如,web层提供支持代码,在J2EE web应用启动过程中自动载入一个Spring
ApplicationContext。
ApplicationContext可以通过编码加载并实例化,对于web应用,Spring提供了可配置的ApplicationContext加载机制。加载器目前有两种选择:
1 : ContextLoaderListener
(基于Servlet2.3版本中新引入的Listener接口实现)
2 : ContextLoaderServlet
(基于Servlet接口实现)
这两者在功能上完全相同
AppFuse中的Spring配置
(1)指定ApplicationContext配置文件的位置,该参数不是必须的如果不指定该参数,web容器会自动加载
WEB-INF/applicationContext.xml, 并实例化ApplicationContext
WEB-INF/web.xml
1
< context
- param
>
2
< param
- name
> contextConfigLocation
</ param
- name
>
3
< param
- value
>/ WEB
- INF
/ applicationContext
-* .xml
</ param
- value
>
4
</
context -
param >
(2)AppFuse中的ApplicationContext加载是通过ContextLoaderListener配置实现的,但是AppFuse不是直接在web.xml配置ContextLoaderListener监听器来实现ApplicationContext的初始化的,而是通过自定义的StartupListener监听器实现配置的。
(3)ApplicationContext的初始化StartupListener 继承了Spring的
ContextLoaderListener接口,并实现:Sevelet的ServletContextListener接口
Web容器启动时,执行StartupListener监听器 StartupListener监听器执行父类ServletContextListener的contextInitialized事件,在该初始化事件中,会调用Spring的contextInitialized事件初始化Spring的ApplicationContext。
1
public
class StartupListener
extends ContextLoaderListener
implements ServletContextListener
{
2
public
void
contextInitialized(ServletContextEvent event)
{
3
//
调用Spring的contextInitialized事件初始化Spring的ApplicationContext
4
super .contextInitialized(event);
5
6
.
7
8
}
9
}
(4) 初始化完ApplicationContext后,就可以通过以下方式引用ApplicationContext来管理beans了:
1
ApplicationContext ctx
=
WebApplicationContextUtils.getRequiredWebApplicationContext(context);
(5)Spring事务管理配置
Spring即提供了对于JDBC,Hibernate Trasaction等依赖特定事务资源的事务处理(即:自己硬编码rollback、commit), 又提供了依赖容器的参数化事务支持(即:又Spring容器管理事务)。使用Hibernate提供的openSessiojnInView技术,即在视图层开启和关闭
Session,在service层进行Transaction管理,这个较为简单,只需要设置一个filter即可,在web.xml中配置
1
< filter
>
2
< filter
- name
> hibernateFilter
</ filter
- name
>
3
< filter
- class
>
org.springframework.orm.hibernate.support.OpenSessionInViewFilter
</ filter
- class
>
4
</
filter >
(6)配置数据源,这里采用Jndi访问方式。
1
< bean id
= "
dataSource "
class
= "
org.springframework.jndi.JndiObjectFactoryBean
" >
2
< property name
= "
jndiName "
>
3
< value
> java:comp
/ env
/ jdbc
/ dudu
</ value
>
4
</ property
>
5
</
bean >
(7)配置SessionFactory,
Hibernate通过SessionFactory创建和维护session,一个session代表了以此数据的访问回话。通过Spring我们就无须通过Hibernage.cfg.xml对SessionFactory进行设定。SessionFactoryj节点的mappingResources属性包含了映射文件的路径。
hibernateProperties节点容纳了所有的属性配置。
1
< bean id
= "
sessionFactory "
class
= "
org.springframework.orm.hibernate3.LocalSessionFactoryBean
" >
2
< property name
= "
dataSource "
ref =
" dataSource
" />
3
< property name
= "
mappingResources
" >
4
< list
>
5
< value
> org
/ appfuse
/ model
/ Role.hbm.xml
</ value
>
6
< value
> org
/ appfuse
/ model
/ User.hbm.xml
</ value
>
7
</ list
>
8
</ property
>
9
< property name
= "
hibernateProperties
" >
10
< props
>
11
< prop key
= "
hibernate.dialect
" >
@HIBERNATE -
DIALECT@ </
prop >
12
< prop key
= "
hibernate.query.substitutions
" >
true
' Y
' ,
false
' N
' </
prop >
13
<!-- Create
/
update the database tables automatically when the JVM starts up
14
< prop key
= "
hibernate.hbm2ddl.auto
" >
update </
prop >
-->
15
<!-- Turn batching off
for
better error messages under PostgreSQL
16
< prop key
= "
hibernate.jdbc.batch_size
" >
0 </
prop >
-->
17
</ props
>
18
</ property
>
19
</
bean >
(8)配置事务管理,引用sessionFactory。
1
< bean id
= "
transactionManager
"
class =
"
org.springframework.orm.hibernate3.HibernateTransactionManager
" >
2
< property name
= "
sessionFactory "
ref =
" sessionFactory
" />
3
</
bean >
(9)配置dataSource、sessionFactory、transactionManager服务器于名为txProxyTemplate的TransactionProxyFactoryBean,
txProxyTemplate的transactionAttributes属性中,定义事务策略。将所有以save、remove开始的方法纳入事务管理范围,如果这些方法抛出异常,在Spring将当前事务回滚,如
果方法正常结束,则提交事务。而对其他所有的方法则以只读的事务处理机制进行,(设为只读性事务,可以是持久层尝试对数据操作进行优化,如对于只读事务hibernate将不执行flush操作,而某些数据库连接池和JDBC驱动也对只读性操作进行了优化),
TransactionProxyFactoryBean使得我们可以脱离每次数据库操作必须首先获得Session实例、启动事务、提交、回滚事务以及繁琐的try/catch/finally的烦杂工作从而获得代码精干集中的逻辑呈献效果。org.springframework.transaction.interceptor.TransactionProxyFactoryBean
利用AOP,将TransactionManager和普通的Service编织起来。
1
< bean id
= "
txProxyTemplate
"
abstract =
" true
"
class =
"
org.springframework.transaction.interceptor.TransactionProxyFactoryBean
" >
2
< property name
= "
transactionManager
" ref
= "
transactionManager
" />
3
< property name
= "
transactionAttributes
" >
4
< props
>
5
< prop key
= "
save* "
> PROPAGATION_REQUIRED
</ prop
>
6
< prop key
= "
remove* "
> PROPAGATION_REQUIRED
</ prop
>
7
< prop key
= "
* "
> PROPAGATION_REQUIRED,readOnly
</ prop
>
8
</ props
>
9
</ property
>
10
</
bean >
(10) 实际的事务处理模板定义
AppFuse没有直接使用txProxyTemplate来管理事务,而是由具体的管理类继承该类,完成具体事务管理。
1
<!--
可以应用在任何对象上进行基本的CRUD操作的 顶级的 manager
-->
2
<
bean id =
" manager
" parent
= "
txProxyTemplate
" >
3
< property name
= "
target "
>
4
< bean
class =
"
org.appfuse.service.impl.BaseManager "
>
5
< property name
= "
dao "
ref =
" dao
" />
6
</ bean
>
7
</ property
>
8
</
bean >
9
10
11
<
bean id =
" userManager
" parent
= "
txProxyTemplate
" >
12
< property name
= "
target "
>
13
< bean
class =
"
org.appfuse.service.impl.UserManagerImpl "
>
14
< property name
= "
userDao "
ref =
" userDao
" />
15
</ bean
>
16
</ property
>
17
< property name
= "
transactionAttributes
" >
18
< props
>
19
< prop key
= "
save* "
> PROPAGATION_REQUIRED,
- UserExistsException
</ prop
>
20
< prop key
= "
remove* "
> PROPAGATION_REQUIRED
</ prop
>
21
< prop key
= "
* "
> PROPAGATION_REQUIRED,readOnly
</ prop
>
22
</ props
>
23
</ property
>
24
< property name
= "
preInterceptors
" >
25
< list
>
26
< ref bean
= "
userSecurityInterceptor
" />
27
</ list
>
28
</ property
>
29
</
bean >
(11) 数据访问形式
1
public
class
UserDAOHibernate
extends BaseDAOHibernate
implements UserDAO
{
2
public
void saveUser(
final User user)
{
3
getHibernateTemplate().saveOrUpdate(user);
4
getHibernateTemplate().flush();
5
}
6
}
(12)以下是一些AppFuse中实现的,辅助的Spring监听器和过滤器
保证Spring所管理的JavaBeans能被正常的初始化和销毁,这个监听器不是 Spring框架必须的。
WEB-INF/web.xml
1
< listener
>
2
< listener
- class
>
3
org.springframework.web.util.IntrospectorCleanupListener
4
</ listener
- class
>
5
</
listener >
(13) 解决Web应用中POST的中文乱码问题,为用户请求定义字符编码,这是因为当前的浏览器一般都不设置字符编码,即便是你在Html文件获Form中设置了字符编码
WEB-INF/web.xml
1
< filter
>
2
< filter
- name
> encodingFilter
</ filter
- name
>
3
< filter
- class
>
org.springframework.web.filter.CharacterEncodingFilter
</ filter
- class
>
4
< init
- param
>
5
< param
- name
> encoding
</ param
- name
>
6
< param
- value
> UTF
- 8
</ param
- value
>
7
</ init
- param
>
8
< init
- param
>
9
< param
- name
> forceEncoding
</ param
- name
>
10
< param
- value
> true
</ param
- value
>
11
</ init
- param
>
12
</
filter >
注:一般的web容器加载Spring的ApplicationContext配置如下:
通过监听器
1
< listener
>
2
< listener
- class
>
3
org.springframework.web.context.ContextLoaderListener
4
</ listener
- class
>
5
</
listener >
或通过Servlet
1
< servlet
>
2
<
servlet
-
name
>
context
</
servlet
-
name
>
3
<
servlet
-
class
>
4
org.springframework.web.context. ContextLoaderServlet
5
</
servlet
-
class
>
6
<
load
-
on
-
startup
>
1
</
load
-
on
-
startup
>
7
</ servlet
>
|