Spring配置补充

一、灵活配置DataSource

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

1、使用外部属性文件配置数据源

既然MyBatis可以引入外部属性文件,那么Spring肯定也是可以的。

在Spring中,使用PropertyPlaceholderConfigurer类可以加载属性文件,在配置文件中采用${...}的方式引用属性文件中的键值对。

 

<!--可引入外部属性文件,配置数据源-->
<bean class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer">
    <property name="location">
    <!--指定属性文件的位置-->
    <value>classpath:data.properties</value>
    </property>
</bean>

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

<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="${driver}" />
    <property name="url">
        <value>${url}</value>
    </property>
    <property name="username" value="${username}" />
    <property name="password" value="${password}" />
</bean>

2、使用JNDI数据源

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

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

<Resource   
   name="jdbc/Demo" 
   auth="Container"   
   type="javax.sql.DataSource"  
   maxActive="100"   
   maxIdle="30"   
   maxWait="10000"  
   username="root"   
   password="****"   
   driverClassName="com.mysql.jdbc.Driver"  
   url="jdbc:mysql://localhost:3306/Demo?useSSL=true&amp;serverTimezone=UTC" 
/>

然后我们修改Spring配置文件,通过JNDI资源定义数据源组件。如下:

<!--使用JNDI资源的方式获取数据库连接-->
<bean id="dataSource_JNDI" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName">
        <value>java:comp/env/jdbc/ShopOrder</value>
    </property>
</bean>

这样一来,在需要引用数据源组件的地方,引用这个数据源Bean的id即可。这种通过JNDI活动数据源的方式很简洁,充分体现了Spring追求简洁的目标。

二、Spring中Bean的作用域

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

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

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

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

<bean id="demoTest" class="ServiceImpl.RoleServiceImpl" scope="prototype">

</bean>

对于使用注解定义的Bean组件,需要使用@Scope注解指定其作用域,如下:

package ServiceImpl;

import Service.BillService;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;


/**
 *  订单服务接口的实现类
 * */
@Scope("prototype")  //指定作用域为prototype
@Service("billService")  //定义Bean组件
public class BillServiceImpl implements BillService {
    //省略实现方法
}

三、Spring的自动装配

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

先介绍autowire属性的几个值:

属性值说明
no不适用自动装配,依赖关系必须由我们自己指定
byType根据属性类型自动装配。BeanFactory查找容器中的全部Bean,如果有一个与需要注入依赖的属性的类型相匹配的Bean,就将这个Bean装配给这个属性。如果有多个相匹配的Bean,Spring将抛出致命异常;如果没有相匹配的Bean,什么都不会发生,最多用的时候会出现空指针。
byName根据属性名自动装配。BeanFactory查找容器中所有的Bean,找出id与属性的setter方法相匹配的Bean,进行注入
constructor与byType的方式类似,不同之处在于它应用于构造器函数。如果容器中没有找到与构造器参数类型一致的Bean,那么将会抛出异常。

自动装配示例:

<bean id="demoTest" class="ServiceImpl.RoleServiceImpl" scope="prototype" autowire="byType" />

如果要配置的Bean有很多,每个Bean都指定autowire也很繁琐。<beans>元素提供了default-autowire属性,影响全局,减少维护单个Bean的注入方式,不需要为每个Bean指定autowire属性,如下:

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
" default-autowire="byType">

</beans>

指定了default-autowire属性,仍然可以为某个Bean单独指定autowire属性,此时会覆盖全局的default-autowire值。

四、拆分Spring配置文件

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

那么我们启动项目的时候,如何指示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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值