Spring中,BeanFactory
提供了一种先进的配置机制来管理任何种类bean(对象), ApplicationContext是BeanFactory的完全超集, 我们大部分时间面对的是ApplicationContext,通过它取得bean,处理bean,而其他的事务管理、远程访问等则交由Spring容器去管理好了。
很多情况下,用户代码不需要实例化BeanFactory, 因为Spring框架代码会做这件事。例如,web层提供支持代码,在J2EE web应用启动过程中自动载入一个Spring ApplicationContext。
ApplicationContext
可以通过编码加载并实例化,对于web应用,Spring提供了可配置的ApplicationContext加载机制。加载器目前有两种选择:ContextLoaderListener和ContextLoaderServlet,这两者在功能上完全相同,只是一个基于Servlet2.3版本中新引入的Listener接口实现,而另一个基于Servlet接口实现。[引用]
● AppFuse
中的Spring配置
(1) 指定ApplicationContext配置文件的位置,该参数不是必须的
如果不指定该参数,web容器会自动加载
WEB-INF/applicationContext.xml,
并实例化
ApplicationContext
Ø
WEB-INF/web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext-*.xml</param-value>
</context-param>
(2) AppFuse中的ApplicationContext加载是通过ContextLoaderListener配置实现的,但是AppFuse不是直接在web.xml配置ContextLoaderListener监听器来实现ApplicationContext的初始化的,而是通过自定义的StartupListener监听器实现配置的。
(3) ApplicationContext的初始化
StartupListener 监听器继承了ContextLoaderListener监听器
和ServletContextListener监听器。
Ø Web
容器启动时,执行StartupListener监听器
Ø StartupListener监听器执行父类ServletContextListener的contextInitialized事件,在该初始化事件中,会调用Spring的contextInitialized事件初始化Spring的ApplicationContext。
public class StartupListener extends ContextLoaderListener
implements ServletContextListener {
public void contextInitialized(ServletContextEvent event) {
// call Spring's context ContextLoaderListener to initialize
// all the context files specified in web.xml
super.contextInitialized(event);
(4) 初始化完ApplicationContext后,就可以通过以下方式
引用ApplicationContext来管理beans了:
ApplicationContext ctx =
WebApplicationContextUtils.getRequiredWebApplicationContext(context);
(5) Spring
事务管理配置
Spring
即提供了对于JDBC,Hibernate Trasaction等依赖特定事务资源的事务处理(即:自己硬编码rollback、commit),又提供了依赖容器的参数化事务支持(即:又Spring容器管理事务)。
使用Hibernate提供的openSessiojnInView技术,即在视图层开启和关闭
Session
,在service层进行Transaction管理,这个较为简单,只需要设置一
个filter即可,在web.xml中配置
<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>org.springframework.orm.hibernate.support.OpenSessionInViewFilter</filter-class>
</filter>
(6) 配置数据源,这里采用Jndi访问方式。
<bean id="dataSource"
class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:comp/env/jdbc/dudu</value>
</property>
</bean>
(7) 配置SessionFactory,Hibernate通过SessionFactory创建和维护session,一个session代表了以此数据的访问回话。通过Spring我们就无须通过Hibernage.cfg.xml对SessionFactory进行设定。
SessionFactoryj节点的mappingResources属性包含了映射文件的路径。
hibernateProperties节点容纳了所有的属性配置。[引用]。
<bean id="sessionFactory"
class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
<property name="dataSource"><ref bean="dataSource"/></property>
<property name="mappingResources">
<list>
<value>org/dudu/model/Role.hbm.xml</value>
<value>org/dudu/model/User.hbm.xml</value>
<value>org/dudu/model/UserCookie.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">net.sf.hibernate.dialect.MySQLDialect
</prop>
<!--prop key="hibernate.show_sql">true</prop-->
<!--prop key="hibernate.hbm2ddl.auto">update</prop-->
</props>
</property>
</bean>
(8) 配置事务管理,引用sessionFactory。
<bean id="transactionManager"
class="org.springframework.orm.hibernate.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory"/>
</property>
</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编织起来。
<bean id="txProxyTemplate" abstract="true"
class="org.springframework.transaction.interceptor.
TransactionProxyFactoryBean">
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
(10) 实际的事务处理模板定义
AppFuse没有直接使用txProxyTemplate来管理事务,而是又具体的管理类继承该类,完成具体事务管理。
<!-- Generic manager that can be used to do basic CRUD operations on any objects -->
<bean id="manager" parent="txProxyTemplate">
<property name="target">
<bean class="org.dudu.service.impl.BaseManager">
<property name="DAO"><ref bean="dao"/></property>
</bean>
</property>
</bean>
<!-- Transaction declarations for business services. To apply a generic
transaction proxy to
all managers, you might look into using the BeanNameAutoProxyCreator -->
<bean id="userManager" parent="txProxyTemplate">
<property name="target">
<bean class="org.dudu.service.impl.UserManagerImpl">
<property name="userDAO"><ref bean="userDAO"/></property>
</bean>
</property>
<!-- Override default transaction attributes b/c of LoginCookie methods -->
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
<prop key="*LoginCookie">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
(11) 数据访问形式
public class UserDAOHibernate extends BaseDAOHibernate implements UserDAO {
public void saveUser(final User user) {
getHibernateTemplate().saveOrUpdate(user);
getHibernateTemplate().flush();
}
}
(12) 以下是一些AppFuse中实现的,辅助的Spring监听器和过滤器
保证Spring所管理的JavaBeans能被正常的初始化和销毁,这个监听器不是
Spring
框架必须的。
Ø
WEB-INF/web.xml
<listener>
<listener-class>
org.springframework.web.util.IntrospectorCleanupListener
</listener-class>
</listener>
(13) 解决Web应用中POST的中文乱码问题,为用户请求定义字符编码,这是因为当前的浏览器一般都不设置字符编码,即便是你在Html文件获Form中设置了字符编码
Ø
WEB-INF/web.xml
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>
org.springframework.web.filter.CharacterEncodingFilte
r
</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
注:一般的web容器加载Spring的ApplicationContext配置如下:
Ø
通过监听器
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
Ø
通过Servlet
<servlet>
<servlet-name>context</servlet-name>
<servlet-class>
org.springfr