Spring配置补充

前言

这篇博文主要拓展Spring的配置。掌握更多配置数据源的方法,理解Bean的作用域,使用
Spring自动装配,会拆分Spring配置文件,下面我们来学习吧!

灵活配置DataSource

Spring与MyBatis的整合过程中,我们将数据源的配置拿到了Spring配置文件中。实际应用中,Spring还有很多灵活配置方式可以选择。

1. 使用属性文件配置

MyBatis可以引入外部属性文件,那么Spring肯定也是可以的。在Spring中,使用PropertyPlaceholderConfigurer类可以加载属性文件,在配置文件中采用${…}的方式引用属性文件中的键值对。

   <!--引入外部文件properties文件-->
    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location">
            <value>classpath:database.properties</value>
        </property>
    </bean>    

引入属性文件之后,我们就可以在配置数据源的时候,应用属性文件中的键值对了,如下:

  <bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassLoader" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${user}"/>
        <property name="password" value="${password}"/>
    </bean>
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/smbms?useUnicode=true&amp;characterEncoding=utf-8
user=root
password=521521

注意:经常有开发者在${…}的前后不小心输入一些空格,这些空格字符串将和变量合并后作为属性的值,最终将引发异常。

2. 使用JNDI数据源

应用部署在高性能的服务器上,我们可能更希望使用服务器本身提高的数据源。服务器的数据源使用JNDI方式供使用者调用。在Spring中,提供了专门引用JNDI资源的JndiObjectFactoryBean类。

使用JNDI资源,首先在服务器上要有这个资源。我们以Tomcat为例,在conf文件夹下的context.xml定义如下数据源:

步骤

  1. 在Tomcat中的lib文件夹下加入数据库驱动包
  2. 在tomcat下的context.xml中配置JDNI数据源,编写连接数据库配置
	<Context>
		<Resource name="jdbc/smbms" auth="Container" type="javax.sql.DataSource"
		maxActive="100" maxIdle="30" maxWait="10000" username="root"
		password="root" driverClassName="com.mysql.jdbc.Driver" 
		url="jdbc:mysql://localhost:3306/数据库?useUnicode=true&amp;characterEncoding=utf-8"/>
	</Context>
  1. 在Spring配置文件中通过JNDI配置DataSource
	<!-- 通过JNDI配置DataSource -->
    <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
        <!--通过jndiName指定引用的JNDI数据源名称 -->
        <property name="jndiName">
            <value>java:comp/env/jdbc/smbms</value>
        </property>
    </bean>

注意:<Resource> 标签的name指定数据源的名称,要与Spring配置文件中的jndiNamejava:comp/env/ 后的名称保持一致。


Spring中Bean的作用域问题

理解Bean的作用域

Spring中定义Bean,除了可以创建Bean实例并对其属性进行注入,还可以为其指定作用域。这个作用域的取值决定了Spring创建该组件实例时所采用的策略,进而影响程序的效率以及数据安全问题。目前Spring划分了5中Bean的作用域:

作用域说明
singleton默认值。Spring以单例模式创建Bean的实例,即容器中该Bean的实例只有一个
prototype每次从容器中获取Bean时,都会创建一个新的实例
request用于Web应用环境,针对每次HTTP请求都会创建一个实例
session用于Web应用环境,同一个会话共享同一个实例,不同的会话使用不同的实例
global sessionPortlet的Web应用中使用,同一个全局会话共享一个实例。对于非Portlet环境,等同于session

作用域详解:

  1. Singleton:单例作用域,是spring容器默认的作用域,使用singleton作用域生成的是单实例,在整个Bean容器中仅保留一个实例对象供所有调用者共享引用。单例模式一般适用于那些无会话状态的Bean(比如辅助工具类,DAO组件,业务逻辑组件等等)
  2. Prototype:原型模式,这是多实例作用域,针对每次不同请求,Bean容器均会生成一个全新的Bean实例以供调用者使用,他适用于那些需要保持会话状态的Bean实例,有一点值得注意:Spring不能对一个property bean的整个生命周期负责,容器在初始化、装配好一个property实例之后,就将他交给客户端,就不管了。因此客户端要负责property实例的生命周期管理
  3. Request:针对每次HTTP请求,spring容器都会根据bean的定义创建一个全新的bean实例,并且该bean实例仅在当前http request内有效,因此可以根据需要放心的更改实例内部状态,而其他请求中根据Bean定义创建的实例,不会看到这些特定于某些请求的状态变化,当处理请求结束,request作用域的Bean实例将被销毁,该作用域仅在基于web的spring ApplicationContext情形下才有效
  4. Session:针对某个HTTP session ,Spring容器会根据bean定义创建一个全新Bean实例,并且该Bean实例仅在当前的HTTP session内有效。该作用域仅在基于web的spring ApplicationContext情形下才有效
  5. Global session:该作用域类似于标准的http session 作用域,不过他仅仅在基于portlet的web应用中才有意义。。。。该作用域仅在基于web的spring ApplicationContext情形下才有效

singleton是默认采用的作用域,即默认情况下Spring为每一个Bean仅创建一个实例,对于不存在线程安全问题的组件,这种方式会大大减少创建对象的开销,提高运行效率。

对于特定的应用场景,比如我们需要每一个用户都相互隔离,使用默认的作用域肯定是实现不了需求的,这时候就需要我们指定Bean组件的作用域为prototype,即每一次获取该组件的实例时都去创建一个新的实例,指定组件的scope属性即可,如下:

<!--设置prototype作用域,作用:每次获取的时候,都会创建新的实例。-->
<bean id="..." class="..." scope="prototype">

</bean>
使用注解指定Bean的作用域
@Scope("prototype")  //指定作用域为prototype
@Service("billService")  //定义Bean组件
public class BillServiceImpl implements BillService {
    //省略实现方法
}

Spring的自动装配

做了解即可(实战中,很少用),大型项目中不推荐使用自动装配,还是指定所依赖的组件好。因为虽然它能够简化配置,但是降低了依赖关系的清晰性和透明性,全都交给Spring自动装配组件,弄得我们都不知道谁依赖谁。而且依赖关系的装配仅依赖于源文件的属性名或者类型,导致Bean与Bean之间的耦合度上升,不利于高层次解耦。

autowrite属性值说明
no不适用自动装配,依赖关系必须由我们自己指定
byType根据属性类型自动装配。BeanFactory查找容器中的全部Bean,如果有一个与需要注入依赖的属性的类型相匹配的Bean,就将这个Bean装配给这个属性。如果有多个相匹配的Bean,Spring将抛出致命异常;如果没有相匹配的Bean,什么都不会发生,最多用的时候会出现空指针。
byName根据属性名自动装配。BeanFactory查找容器中所有的Bean,找出id与属性的setter方法相匹配的Bean,进行注入
constructor与byType的方式类似,不同之处在于它应用于构造器函数。如果容器中没有找到与构造器参数类型一致的Bean,那么将会抛出异常。
1. 采用传统的xml方式配置Bean组件
	<!-- 配置UserMapper -->
	<bean id="userMapper" class="cn.smbms.dao.user.UserMapperImpl">
		<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
	</bean> 
	
	<!-- 配置业务Bean并注入DAO实例 -->
	<bean id="userService" class="cn.smbms.service.user.UserServiceImpl">
		<property name="userMapper" ref="userMapper"/>
	</bean> 
2 使用自动装配
	<!--配置DAO 根据属性名称自动装配  -->
	<bean id="userMapper" class="cn.smbms.dao.user.UserMapperImpl" autowire="byName"/>
	
	<!-- 配置业务bean,根据属性名称自动装配 -->
	<bean id="userService" class="cn.smbms.service.user.UserServiceImpl" autowire="byName"/>
3. 全局自动匹配
<beans default-autowire="byName"/>
	<!--省略部分代码-->
</beans>

拆分Spring配置文件

使用XML方式进行配置Spring项目,如果项目很大,配置文件的可读性、可维护性较差,庞大的Spring配置文件难以维护、阅读。此外,在团队开发时,多人修改同一配置文件容易产生问题冲突。我们可以将一个大的配置文件进行拆分,每一个小的配置文件只配置功能相似的组件,比如application_dao.xml,application-service.xml,降低配置文件的修改难度。

为什么需要拆分配置文件

  • 项目规模变大,配置文件可读性、可维护性差
  • 团队开发时,多人修改同一配置文件,易发生冲突

拆分策略

  • 公用配置+每个系统模块一个单独配置文件(包含DAO、Service、Web控制器)

  • 公用配置+DAO Bean配置+业务逻辑Bean配置+Web控制器配置

启动项目的时候,如何指示Spring找到这些多个配置文件,将它们整合到一起呢?

根据ClassPathXmlApplicationContext类的构造方法的几种重载:

public ClassPathXmlApplicationContext(String configLocation);

public ClassPathXmlApplicationContext(String… configLocations);

方式一:

ApplicationContext context=new ClassPathXmlApplicationContext("application-mybatis.xml",
            "application-dao.xml",
            "application-service.xml");

方式二:

String[] locations={"application-mybatis.xml","application-dao.xml","application-service.xml"};
ApplicationContext context=new ClassPathXmlApplicationContext(locations);

方式三:

ApplicationContext context=new ClassPathXmlApplicationContext("application-*.xml");

使用通配符可以导入多个配置文件,很方便,但是命名规范一定要好,遵循一定的命名规律。

此外,Spring配置文件本身也可以通过import子元素导入外部配置文件,将多个配置文件整合到一起,最后只需要加载终极配置文件即可,例如在application-mybatis.xml中引入以下两个配置文件:

<import resource="application-dao.xml" />
<import resource="application-service.xml"/>

上面的方式用下面的方式加载

ApplicationContext context=new ClassPathXmlApplicationContext("application-mybatis.xml");

总结

这篇博文来自课本的总结,希望对大家有帮助

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值