依赖配置详解

   bean的属性及构造器参数既可以引用容器中的其他bean,也可以是内联(inline)bean。在spring的XML配置中使用和元素定义。

直接变量(基本类型、Strings类型等。)

  <value/>元素通过人可以理解的字符串来指定属性或构造器参数的值。正如前面所提到的,JavaBean PropertyEditor将用于把字符串从java.lang.String类型转化为实际的属性或参数类型。

<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">

  <property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost:3306/mydb</value>
</property>
<property name="username">
<value>root</value>
</property>
<property name="password">
<value>masterkaoli</value>
</property>
</bean>

  <property/> 和<constructor-arg/> 元素中也可以使用'value' 属性,这样会使我们的配置更简洁,比如下面的配置

<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">

  <!-- results in a setDriverClassName(String) call -->
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
<property name="username" value="root"/>
<property name="password" value="masterkaoli"/>
</bean>

   Spring团队更倾向采用属性方式(使用元素)来定义value值。当然我们也可以按照下面这种方式配置一个java.util.Properties实例

<bean id="mappings" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

   <!-- typed as a java.util.Properties -->
<property name="properties">
<value>
jdbc.driver.className=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mydb
</value>
</property>
</bean>

  如果采用上面的配置,Spring容器将使用JavaBean PropertyEditor把元素中的文本转换为一个java.util.Properties实例

idref元素

  idref元素用来将容器内其它bean的id传给 或 元素,同时提供错误验证功能。(如果使用元素指定拦截器名字,可以避免因一时疏忽导致的拦截器ID拼写错误。)

<bean id="theTargetBean" class="..."/>

<bean id="theClientBean" class="...">
<property name="targetName">
<idref bean="theTargetBean" />
</property>
</bean>

  上述bean定义片段完全地等同于(在运行时)以下的片段:

<bean id="theTargetBean" class="..." />

<bean id="client" class="...">
<property name="targetName" value="theTargetBean" />
</bean>

  第一种形式比第二种更可取的主要原因是,使用idref标记允许容器在部署时 验证所被引用的bean是否存在。而第二种方式中,传给client bean的targetName属性值并没有被验证。任何的输入错误仅在client bean实际实例化时才会被发现(可能伴随着致命的错误)。如果client bean 是prototype类型的bean,则此输入错误(及由此导致的异常)可能在容器部署很久以后才会被发现。

  此外,如果被引用的bean在同一XML文件内,且bean名字就是bean id,那么可以使用local属性,此属性允许XML解析器在解析XML文件时对引用的bean进行验证

<property name="targetName">
<idref local="theTargetBean"/>
</property>

引用其它的bean(协作者)

  在元素内部还可以使用ref元素。该元素用来将bean中指定属性的值设置为对容器中的另外一个bean的引用。如前所述,该引用bean将被作为依赖注入,而且在注入之前会被初始化(如果是singleton bean则已被容器初始化)。尽管都是对另外一个对象的引用,但是通过id/name指向另外一个对象却有三种不同的形式,不同的形式将决定如何处理作用域及验证。

  第一种形式也是最常见的形式是通过使用标记指定bean属性的目标bean,通过该标签可以引用同一容器或父容器内的任何bean(无论是否在同一XML文件中)。XML 'bean'元素的值既可以是指定bean的id值也可以是其name值

  <ref bean="someBean"/>

  第二种形式是使用ref的local属性指定目标bean,它可以利用XML解析器来验证所引用的bean是否存在同一文件中。local属性值必须是目标bean的id属性值。如果在同一配置文件中没有找到引用的bean,XML解析器将抛出一个例外。如果目标bean是在同一文件内,使用local方式就是最好的选择(为了尽早地发现错误)。

  <ref local="someBean"/>

  第三种方式是通过使用ref的parent属性来引用当前容器的父容器中的bean。parent属性值既可以是目标bean的id值,也可以是name属性值。而且目标bean必须在当前容器的父容器中。使用parent属性的主要用途是为了用某个与父容器中的bean同名的代理来包装父容器中的一个bean(例如,子上下文中的一个bean定义覆盖了他的父bean)。

<!-- in the parent context -->

	<bean id="accountService" class="com.foo.SimpleAccountService">
</bean>
<!-- in the child (descendant) context -->

<bean id="accountService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<ref parent="accountService"/>
</property>
</bean>

内部bean

  所谓的内部bean(inner bean)是指在一个bean的或 元素中使用元素定义的bean。内部bean定义不需要有id或name属性,即使指定id 或 name属性值也将会被容器忽略。

	<bean id="outer" class="...">
<property name="target">
<bean class="com.example.Person">
<property name="name" value="Fiona Apple"/>
<property name="age" value="25"/>
</bean>
</property>
</bean>

  注意:内部bean中的scope标记及id或name属性将被忽略。内部bean总是匿名的且它们总是prototype模式的。同时将内部bean注入到包含该内部bean之外的bean是不可能的。

集合(重点)

  通过<list/>、<set/>、<map/><props/>元素可以定义和设置与Java Collection类型对应List、Set、MapProperties的值。

<bean id="moreComplexObject" class="example.ComplexObject">
<!-- results in a setAdminEmails(java.util.Properties) call -->
<property name="adminEmails">
<props>
<prop key="administrator">administrator@example.org</prop>
<prop key="support">support@example.org</prop>
<prop key="development">development@example.org</prop>
</props>
</property> <!-- results in a setSomeList(java.util.List) call -->
<property name="someList">
<list>
<value>a list element followed by a reference</value>
<ref bean="myDataSource" />
</list>
</property> <!-- results in a setSomeMap(java.util.Map) call -->
<property name="someMap">
<map>
<entry>
<key>
<value>an entry</value>
</key>
<value>just some string</value>
</entry>
<entry>
<key>
<value>a ref</value>
</key>
<ref bean="myDataSource" />
</entry>
</map>
</property> <!-- results in a setSomeSet(java.util.Set) call -->
<property name="someSet">
<set>
<value>just some string</value>
<ref bean="myDataSource" />
</set>
</property>
</bean>

map的key或value值,或set的value值还可以是以下元素:

bean | ref | idref | list | set | map | props | value | null

注入值(基本、集合)

  注入基本类型的值、注入集合类型的值

	<bean id="eb" class="basic.ExampleBean">
<property name="name" value="C罗"/>
<property name="age" value="22"/>
<property name="cities">
<list>
<value>北京</value>
<value>岳阳</value>
<value>长沙</value>
<!-- 允许重复元素 -->
<value>长沙</value>
</list>
</property>
<property name="interest">
<set>
<value>钓鱼</value>
<value>做饭</value>
<value>编程</value>
<!-- 不允许重复元素 -->
<value>编程</value>
</set>
</property>
<property name="score">
<map>
<entry key="english" value="59.5"/>
<entry key="math" value="69.5"/>
</map>
</property>
<property name="db">
<props>
<prop key="username">Tom</prop>
<prop key="password">1234</prop>
</props>
</property>
</bean>

  将集合类型的值当做一个bean来配置。命名空间(namespace):为了区分同名元素而在

	 <util:list id="citiesBean">
<value>北京</value>
<value>武汉</value>
<value>济南</value>
</util:list>
<util:set id="interestBean">
<value>台球</value>
<value>钓鱼</value>
<value>做饭</value>
</util:set>
<util:map id="scoreBean">
<entry key="english" value="80"/>
<entry key="math" value="90"/>
</util:map>
<util:properties id="dbBean">
<prop key="username">Tom</prop>
<prop key="password">1234</prop>
</util:properties>
<bean id="eb2" class="basic.ExampleBean">
<property name="cities" ref="citiesBean"/>
<property name="interest" ref="interestBean"/>
<property name="score" ref="scoreBean"/>
<property name="db" ref="dbBean"/>
</bean> <!--
读取location指定位置的文件的内容。
classpath:是spring框架内部的约定。
-->
<util:properties id="config"
location="classpath:config.properties"/>

集合的合并

  Spring IoC容器支持集合的合并。这样我们可以定义parent-stylechild-style的、、或元素,子集合的值从其父集合继承和覆盖而来;也就是说,父子集合元素合并后的值就是子集合中的最终结果,而且子集合中的元素值将覆盖父集全中对应的值

  注意,关于合并的这部分利用了parent-child bean机制

<beans>
<bean id="parent" abstract="true" class="example.ComplexObject">
<property name="adminEmails">
<props>
<prop key="administrator">administrator@example.com</prop>
<prop key="support">support@example.com</prop>
</props>
</property>
</bean>
<bean id="child" parent="parent">
<property name="adminEmails">
<!-- the merge is specified on the *child* collection definition -->
<props merge="true">
<prop key="sales">sales@example.com</prop>
<prop key="support">support@example.co.uk</prop>
</props>
</property>
</bean>
<beans>

在上面的例子中,childbean的adminEmails属性的元素上使用了merge=true属性。当child bean被容器实际解析及实例化时,其 adminEmails将与父集合的adminEmails属性进行合并。

administrator=administrator@example.com
sales=sales@example.com
support=support@example.co.uk

  子bean的Properties集合将从父继承所有属性元素。同时子bean的support值将覆盖父集合的相应值。不同的集合类型是不能合并(如map和 list是不能合并的),否则将会抛出相应的Exception。

XML配置文件的简写及其他

  配置元数据冗长不是什么好事情,因此我们将通过下面的方式来对配置进行“减肥”,第一种做法就是通过使用<property/>来定义值和对其他bean的引用,另一个做法就是采用不同的属性定义格式

基于XML配置元数据

  <property/>、<constructor-arg/>及<entry/>元素都支持value属性(attribute),它可以用来替代内嵌的<value/>元素。

<property name="myProperty">
<value>hello</value>
</property>
<constructor-arg>
<value>hello</value>
</constructor-arg>
<entry key="myKey">
<value>hello</value>
</entry>
```
等同于:
```
<property name="myProperty" value="hello"/>
```
```
<constructor-arg value="hello"/>
```
```
<entry key="myKey" value="hello"/>
```
**&lt;property/>和&lt;constructor-arg/>**支持类似ref的简写属性,它可用来替代整个内嵌的&lt;ref/>元素。因而,以下的代码:
```
<property name="myProperty">
<ref bean="myBean">
</property>
```
```
<constructor-arg>
<ref bean="myBean">
</constructor-arg>
```
等同于:
```
<property name="myProperty" ref="myBean"/>
```
```
<constructor-arg ref="myBean"/>
```
注意,尽管存在等同于**&lt;ref bean="xxx">** 元素的简写形式,但并**没有&lt;ref local="xxx">**的简写形式,为了对当前xml中bean的引用,你只能使用完整的形式。 最后,map中entry元素的简写形式为**key/key-ref** 和 **value /value-ref**属性,因而,以下的代码:
```
<entry>
<key>
<ref bean="myKeyBean" />
</key>
<ref bean="myValueBean" />
</entry>
```
等同于:
```
<entry key-ref="myKeyBean" value-ref="myValueBean"/>
``` ### 使用p名称空间配置属性 ###
  事实上,我们所看到的所有bean的配置格式都是基于一个 **XML Schema**文档。
  特定的名称空间并不需要定义在一个XSD文件中,它只在**Spring内核中**存在。我们所说的**p名称空间**就是这样,它不需要一个schema定义,与我们前面采用<property/>元素定义bean的属性不同的是,当我们采用了p名称空间,我们就可以**在bean元素中使用属性(attribute)来描述**bean的property值。   下面的两段XML配置文件中都是用来定义同一个bean:一个采用的是标准的XML格式,一个是采用p名称空间。
```
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean name="classic" class="com.example.ExampleBean">
<property name="email" value="foo@bar.com/>
</bean> <bean name="p-namespace" class="com.example.ExampleBean"
p:email="foo@bar.com"/>
</beans>
```
  从上面的bean定义中,我们采用p名称空间的方式包含了一个叫email的属性,而Spring会知道我们的bean包含了一个属性(property)定义。我们前面说了,p名称空间是**不需要schema**定义的,因此属性**(attribute)的名字就是你bean的property**的名字。   下面的例子包含了两个bean定义,它们都引用了另一个bean
```
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean name="john-classic" class="com.example.Person">
<property name="name" value="John Doe"/>
<property name="spouse" ref="jane"/>
</bean> <bean name="john-modern"
class="com.example.Person"
p:name="John Doe"
p:spouse-ref="jane"/> <bean name="jane" class="com.example.Person">
<property name="name" value="Jane Doe"/>
</bean>
</beans>
```   上面的例子不仅使用p名称空间包含了一个属性(property)值,而且使用了一个特殊的格式声明了一个属性引用。在第一个bean定义中使用了**&lt;property name="spouse" ref="jane"/>**来建立beanjohn到beanjane的引用,而第二个bean定义则采用**p:spouse-ref="jane**"属性(attribute)的方式达到了同样的目的。在这个例子中,"**spouse"是属性(property)名,而"-ref“则用来说明该属性不是一个具体的值而是对另外一个bean的引用。** ### depends-on ###
  **depends-on属性可以用于当前bean初始化之前显式地强制一个或多个bean被初始化**。下面的例子中使用了depends-on属性来指定一个bean的依赖。
```
<bean id="beanOne" class="ExampleBean" depends-on="manager"/> <bean id="manager" class="ManagerBean" />
```
  若需要**表达对多个bean的依赖**,可以在'depends-on'中将指定的多个bean名字用分隔符进行分隔,分隔符可以是逗号、空格及分号等。下面的例子中使用了'depends-on'来表达对多个bean的依赖。
```
<bean id="beanOne" class="ExampleBean" depends-on="manager,accountDao">
<property name="manager" ref="manager" />
</bean> <bean id="manager" class="ManagerBean" />
<bean id="accountDao" class="x.y.jdbc.JdbcAccountDao" />
```
  **注意**
  “depends-on”属性不仅用来**指定初始化时的依赖**,同时也用来**指定相应的销毁时的依赖**(该依赖只针对singletonbean)。depends-on属性中指定的依赖bean会**在相关bean销毁之前被销毁**,从而可以让用户控制销毁顺序。
## 延迟初始化bean ##
**  默认情况下,容器启动之后,会将所用作用域为
   singleton的bean创建好。
   可以设置lazy-init属性为true,表示延迟加载**
  ApplicationContext实现的默认行为就是在**启动时将所有singleton bean提前进行实例化**。提前实例化意味着作为初始化过程的一部分,ApplicationContext实例会创建并配置所有的singleton bean。通常情况下这是件好事,因为这样在配置中的任何错误就会即刻被发现(否则的话可能要花几个小时甚至几天)。   有时候这种默认处理可能并不是你想要的。如果你不想让一个singleton bean在ApplicationContext初始化时被提前实例化,那么可以将bean设置为延迟实例化。一个延迟初始化bean将告诉IoC 容器是在启动时还是在第一次被用到时实例化。   在XML配置文件中,延迟初始化将通过<bean/>元素中的**lazy-init属性**来进行控制。例如:
```
<bean id="lazy" class="com.foo.ExpensiveToCreateBean" lazy-init="true"/> <bean name="not.lazy" class="com.foo.AnotherBean"/>
```
  当ApplicationContext实现加载上述配置时,设置为lazy的bean将不会在ApplicationContext启动时提前被实例化,而not.lazy却会被提前实例化。   需要说明的是,如果一个**bean被设置为延迟初始化**,而另一个**非延迟初始化**的singleton bean**依赖于它**,那么当ApplicationContext提前实例化singleton bean时,它必须也确保所有上述singleton 依赖bean也被预先初始化,当然也包括设置为延迟实例化的bean。因此,如果Ioc容器在启动的时候创建了那些设置为延迟实例化的bean的实例,你也不要觉得奇怪,因为那些延迟初始化的bean可能在配置的某个地方被注入到了一个非延迟初始化singleton bean里面。   在容器层次上通过在<beans/>元素上使用'default-lazy-init'属性来控制延迟初始化也是可能的。如下面的配置:
```
<beans default-lazy-init="true">
<!-- no beans will be pre-instantiated... -->
</beans>
```

Spring(二)之配置.md的更多相关文章

  1. 用IntelliJ IDEA 开发Spring+SpringMVC+Mybatis框架 分步搭建二:配置MyBatis 并测试(1 构建目录环境和依赖)

    引言:在用IntelliJ IDEA 开发Spring+SpringMVC+Mybatis框架 分步搭建一   的基础上 继续进行项目搭建 该部分的主要目的是测通MyBatis 及Spring-dao ...

  2. 从零开始学 Java - Spring 集成 ActiveMQ 配置(二)

    从上一篇开始说起 上一篇从零开始学 Java - Spring 集成 ActiveMQ 配置(一)文章中讲了我关于消息队列的思考过程,现在这一篇会讲到 ActivMQ 与 Spring 框架的整合配置 ...

  3. Maven 工程下 Spring MVC 站点配置 (二) Mybatis数据操作

    详细的Spring MVC框架搭配在这个连接中: Maven 工程下 Spring MVC 站点配置 (一) Maven 工程下 Spring MVC 站点配置 (二) Mybatis数据操作 这篇主 ...

  4. 用IntelliJ IDEA 开发Spring+SpringMVC+Mybatis框架 分步搭建二:配置MyBatis 并测试(2 配置spring-dao和测试)

    用IntelliJ IDEA 开发Spring+SpringMVC+Mybatis框架 分步搭建二:配置MyBatis 并测试(1 搭建目录环境和依赖) 四:在\resources\spring 下面 ...

  5. Spring Boot 启动(二) 配置详解

    Spring Boot 启动(二) 配置详解 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) Spring Boot 配置 ...

  6. SpringBoot学习(二)-->Spring的Java配置方式

    二.Spring的Java配置方式 Java配置是Spring4.x推荐的配置方式,可以完全替代xml配置. 1.@Configuration 和 @Bean Spring的Java配置方式是通过 @ ...

  7. SpringBoot学习(二)——Spring的Java配置方式

    Java配置是Spring4.x推荐的配置方式,可以完全替代xml配置. 一.@Configuration 和 @Bean Spring的Java配置方式是通过@Configuration和@Bean ...

  8. Spring Security认证配置(二)

    学习本章之前,可以先了解下上篇Spring Security基本配置. 本篇想要达到这样几个目的: 1.访问调用者服务时,如果是html请求,则跳转到登录页,否则返回401状态码和错误信息 2.调用方 ...

  9. SpringMVC之二:配置 Spring MVC

    Servlet 3.0规范在2009年12月份就发布了,因此很有可能你会将应用部署到支持Servlet 3.0的Servlet容器之中,如tomcat7.0及以上.在Servlet 3 规范中,可以使 ...

随机推荐

  1. voa 2015.4.29

    Nepal has declared three days of mourning for the victims of Saturday's 7.8 magnitude earthquake tha ...

  2. python学习笔记之运算符

    目录 前言 软件环境 身份运算符 算术运算符 比较运算符 位移运算符 自变运算符 位运算符 逻辑运算符 成员关系运算符 Python真值表 最后 前言 在前面的博文介绍了Python的数据结构之后,接 ...

  3. js实现图片旋转、模板文件查看图片大图之记录篇[二]

    一个小小的前端需求送给大家,使用js实现图片旋转,并且点击图片能够实现规定格式的大图. 主要使用的是jQuery的delegate()方法实现图片旋转,该方法主要的功能就是给某个组件绑定一个或一组事件 ...

  4. 中文里带半角空格导致的Text换行问题[Unity]

    0x01 问题 最近策划反映了个问题,游戏里的多行文本会出现提前换行的问题,如下图所示: 文本错误地提前换行,导致第一行文本后面有大块空白区域 通过观察可以发现,当字符串中带有半角空格,且半角空格后面 ...

  5. Gym 100952 D. Time to go back(杨辉三角形)

    D - Time to go back Gym - 100952D http://codeforces.com/gym/100952/problem/D D. Time to go back time ...

  6. Phpcms安装前后域名默认访问路径

    一.安装前 phpcms下载后index.html文件内容如下图,在本地服务器配置项目虚拟域名后,访问域名后直接跳到:域名/install/install.php,然后出现安装界面. 二.安装之后 提 ...

  7. 51nod_1298:圆与三角形(计算几何)

    题目链接 判断圆和三角形是否相交   可以转化为   判断三条线段是否和圆相交 #include<iostream> #include<cstdio> #include< ...

  8. golang windows 安装方法

    编译器下载链接:https://golang.org/dl/ 默认安装到C盘,不用修改.   添加环境变量:     配置环境变量:   注:C:\mygo\bin 配置这个后,则可以直接在 Dos ...

  9. ES6数组扩展

    前面的话 数组是一种基础的JS对象,随着时间推进,JS中的其他部分一直在演进,而直到ES5标准才为数组对象引入一些新方法来简化使用.ES6标准继续改进数组,添加了很多新功能.本文将详细介绍ES6数组扩 ...

  10. android studio友盟分享

    这个东西搞了整整两天真是把我搞郁闷着了,官方demo下载后,根据提示的错误,修改了一个小bug之后,便能直接运行,但是不管我如何集成到自己app上,分享时APP都会黑屏Crash,并且代码都与官方de ...