1. 多种方式配置数据源
1.1 properties 文件方式
Spring 支持从属性文件中获取信息来进行数据源配置。使用 Spring 提供的 PropertyPlaceHolderConfigurer 类可以加载属性文件。在Spring 配置文件中采用 ${…} 的方式引用属性文件中的键值对。如下示例:
<!--引入properties文件-->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:database.properties"/>
</bean>
<!--配置 DataSource-->
<bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</bean>
</beans>
database.properties属性文件中的内容:
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/smbms?useUnicode=true&characterEncoding=UTF-8
username=root
password=121127
1.2 Spring 对 JNDI 数据源的支持
Spring 提供了专门引用 JNDI 资源的 JndiObjectFactory Bean类,以便开发者能够通过 JNDI 方式使用应用服务器(Tomcat、WebLogic等)本身提供的数据源。
使用 JNDI 的方式配置数据源,前提是必须在应用服务器上配置好数据源。以Tomcat为例,配置数据源需要把数据库驱动文件放到 Tomcat 的lib目录下,并修改 Tomcat 的conf 目录下的context.xml 文件,配置数据源代码如下所示:
<Context>
<Resource name="jdbc/news"
auth="Container"
type="javax.sql.DataSource"
maxActive="100"
maxIdle="30"
maxWait="10000"
username="root"
password="121127"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://locathost:3306/kgcnews?characterEncoding=utf-8"/>
</Context>
<Resource>标签的 name 属性指定了数据源的名称,要与Spring 配置文件中的jndiName 值java:comp/env/ 后的名称保持一致。Spring 配置文件内容如下所示:
<!--通过 JNDI 配置 DataSource-->
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<!--通过 jndiName 指定引用的JNDI数据源名称-->
<property name="jndiName" value="java:comp/env/jdbc/smbms" />
</bean>
2. 深入理解和配置 Bean 的作用域
2.1 Spring 中的 Bean 的 5 个作用域
在 Spring 中定义Bean,除了可以创建 Bean 实例并对 Bean 的属性进行注入外,还可以为定义的Bean 指定一个作用域。这个作用域的取值决定了 Spring 创建该组件实例的策略,进而影响程序的运行效率和数据安全。在Spring2.0 版本以及之后的版本中,Bean的作用域被分为如下5种:
作用域 | 说明 |
---|---|
singleton | 默认值。一单例模式创建Bean的实例,即容器中该Bean的实例只有一个 |
prototype | 每次从容器中获取Bean时,都会创建一个新的实例 |
request | 用于Web应用环境,针对每次HTTP请求都会创建 一个实例 |
session | 用于Web应用环境,同一个会话共享同一个实例,不同的会话使用不同的实例 |
globe session | 仅在Portlet的Web应用中使用,同一个全局会话共享一个实例。对于非Protlet 环境,等同于 session |
single 是默认的作用域, 即默认情况下 Spring 为每个Bean 仅创建一个实例。对于不存在线程安全问题的组件,采用这种方式可以大大减少创建对象的开销,提高运行效率。而对于存在线程安全问题的组件,可以使用 prototype 作用域,设置 scope 属性。
示例如下:
<!--指定 Bean 的作用域为 prototype-->
<bean id="..." class="..." scope="prototype">
...
</bean>
Spring 在每次获取该组件时,都会创建一个新的实例,避免因为共用同一个实例而产生线程问题。
2.2 使用注解指定 Bean 的作用域
对于使用注解声明的 Bean 组件,如需修改其作用域,可以使用 @Scop 注解实现。
3.基于XML 配置 Spring 的自动装配
基于 XML 配置的 Spring 自动装配代码示例如下:
<!--配置 DAO , 根据属性名称自动装配-->
<bean id="userMapper" class="dao.impl.UserMapperImpl"
autowire="byName"/>
<!--配置 service,根据属性明自动装配-->
<bean id="userService" class="service.impl.UserServiceImpl"
autowire="byName"/>
上述示例中通过 <bean> 元素的 autowire 属性指定自动装配,代替了通过<property> 标签显示指定 Bean 的依赖关系。有 BeanFactory 检查 XML 配置文件的内容,为Bean 自动注入依赖关系,大大简化了维护 Bean 注入的配置。
Spring 提供了多种自动装配方式, autowire 属性常用的取值如下:
autowire属性值 | 说明 |
---|---|
no | 不使用自动装配。 Bean依赖关系必须通过 property 元素定义 |
byType | 根据属性类型自动装配。 BeanFactory 查找容器中的全部 Bean, 如果正好有一个与依赖属性类型相同的Bean,就会自动装配这个属性;如果有多个这样的Bean ,Spring 无法决定注入哪个 Bean,就会抛出一个致命异常;如果没有匹配的Bean,就什么都不会发生,属性不会被设置 |
byName | 根据属性名自动装配。BeanFactory 查找容器中全部 Bean ,找出 id 与属性的setter 方法匹配的Bean 。找到即自动注入,否则什么也不会做 |
constructor | 与byType 的方式类似,不同之处在于它应用于构造器参数。如果在容器中没有找到与构造器参数类型一致的 Bean ,那么将会抛出异常 |
可以通过<beans>元素的 default-autowire 属性影响全局,减少维护单个 Bean 的注入方式。如果在 <beans>节点上设置 default-autowire 时,依然可以为<bean>节点设置 autowire 属性。这是该<bean> 节点上的自动装配设置将覆盖全局设置,成为该 Bean 的自动装配策略。
4. Spring 配置文件的查分策略和拆分方法
4.1拆分的策略
拆分的两种方式:
一、如果一个开发人员负责一个模块,可以采用公用配置(包含数据源、事务等)+每个系统模块一个单独配置文件(包含Dao 、 Service 及 Web 控制器)的形式。
二、如果开发是按照分层进行的分工,我们采用公用配置(包含数据源、事务等)+ DAO Bean 配置+ 业务逻辑 Bean 配置 + Web控制情配置的形式。
两种拆分策略各有特色,拆分 Spring 配置文件,不仅可以分散配置文件,降低修改配置文件的难度和冲突的风险,而且更符合“分而治之”的软件工程原理。
4.2 拆分的方法
完成 Spring 配置文件的拆分以后,Spring 如何找到拆分后的配置文件?
1、通过 ClassPathXmlApplicationContext 类的构造方法的几种重载形式,通过传入参数的方式将配置文件加载进Spring:
ClassPathXmlApplicationContext()
ClassPathXmlApplicationContext(ApplicationContext parent)
ClassPathXmlApplicationContext(String configLocation)
ClassPathXmlApplicationContext(String... configLocations)
ClassPathXmlApplicationContext(String[] configLocations, ApplicationContext parent)
ClassPathXmlApplicationContext(String[] configLocations, boolean refresh)
ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
ClassPathXmlApplicationContext(String path, Class<?> clazz)
ClassPathXmlApplicationContext(String[] paths, Class<?> clazz)
ClassPathXmlApplicationContext(String[] paths, Class<?> clazz, ApplicationContext parent)
2、或者可以通过通配符(*) 来加载多个具有一定命名规则的配置文件,代码如下:
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext *.xml");
3、Spring 配置文件本身也可以通过 import 子元素导入其他配置文件,将多个配置文件整合到一起,形成一个完整的 Spring 配置文件。用法示例如下:
<import resource="applicationContext-dao.xml"/>
<import resource="applicationContext-service.xml"/>