依赖
依赖与配置细节
直接数值
<property>元素的value值可以直接设置为人类可读的字符串形式,Spring会自动将其转换为内置类型。例如,字符串转整数。
package examples;
import java.util.Properties;
public class Example {
Properties properties;
public void setProperties(Properties properties) {
this.properties = properties;
}
}
<bean id="example" class="Examples.example">
<property name="properties">
<value>
s=sss
i=123
</value>
</property>
</bean>
ps:Spring容器使用JavaBeans的PropertiesEditor机制将value中的文本转化为java.util.Properties实例。
idref元素是一种传递其他bean的id的一种可检验的方法。
<bean name="example" "examples.Example">
<property name="foo">
<idref bean="foo" />
</property>
</bean>
<bean name="foo" class="example.Example"/>
ps:这种方法会在配置阶段(bean已经被创建)检验是否有手写错误。
ps:spring4.0之后,使用idref bean代替idref local。
ps:ProxyBeanFactory的bean定义中的AOP拦截器配置是常使用idref配置的地方。此处使用idref元素,防止拦截器名称拼错。
其他beans的引用
通过<ref>元素的bean属性指定一个目标bean是一种允许创建一个引用存在于当前容器或父容器中的任何一个对象的引用的常见形式,即使bean并不位于同一个xml文件。
<ref bean="example">
通过parent属性可以创建一个指向当前容器的父容器中的bean的引用。
parent的值可以为bean的id或bean的name中的任意一个值,而这个bean必须位于当前容器的父容器。
通常使用这种方式将一个存在于父容器中的bean包装为一个同名代理。
内部bean
定义在property元素或constructor-arg元素中的bean元素被称为内部bean。
内部bean不需要定义name或id,就算定义了,Spring框架也不会将其作为一个标识符来进行处理。
内部bean总是匿名且在外部bean被创建时创建。
内部bean不会被独立访问,也不会作为依赖被注入其他bean中。
集合
<list/>、<set/>、<map/>与<props/>元素分别用于设置Java Collection类型List、Set、Map与Properties的值。
<bean id="example" class="examples.Example">
<property name="properties">
<props>
<prop key="aaa">sss</prop>
</props>
<property/>
<property name="list">
<list>
<value>ssss</value>
</list>
<property/>
<property name="map">
<map>
<entry key="aaa" value="sss" />
<entry key="foo" value-ref="foo"/>
</map>
<property/>
<property name="set">
<set>
<ref bean="foo" />
</set>
<property/>
</bean>
Spring容器支持集合合并,即孩子集合的值为双亲集合与孩子集合的合并,孩子集合的值会重载双亲集合的值。
<beans>
<bean id="parent" abstract="true" class="example.ComplexObject">
<property name="adminEmails">
<props>
<prop key="administrator">[email protected]</prop>
<prop key="support">[email protected]</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">[email protected]</prop>
<prop key="support">[email protected]</prop>
</props>
</property>
</bean>
<beans>
ps:使用merge属性合并集合。
List元素的底层有排序的概念,所以,合并集合时,双亲集合的元素全部位于子集合元素之前。
合并不同类型的集合时,会导致抛出异常。并且合并集合只有在子bean与双亲bean之间才成立,在双亲bean上设置合并集合没有任何意义。
当使用使用的集合通过类型参数指定了元素类型,Spring会使用内置的类型转换机制进行类型转化。
package examples;
public class Example{
private Map<String, Float> data;
public void setData(Map<String, Float> data) {
this.data = data;
}
}
<bean id="example" class="examples.Example">
<property name="data">
<map>
<entry key="aaa" value="12.4" />
</map>
</property>
</bean>
null与空字符串
Spring处理属性的空参数值如同空字符串。如果想要将null传入,需要使用<null>标签。
<bean class="examples.Example">
<property name="sss">
<null/>
</propety>
</bean>
使用p-namspace的xml缩写
p-namspace的允许使用bean的属性替代<property>子元素来描述属性值或协作bean。
Spring支持的可扩展的使用namespace的配置格式基于XML Schema定义。
<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.xsd">
<bean name="classic" class="com.example.ExampleBean">
<property name="email" value="[email protected]"/>
<property name="foo" ref="bean"/>
</bean>
<bean name="p-namespace" class="com.example.ExampleBean"
p:email="[email protected]"
p:foo-ref="foo"/>
<bean name="foo" class="examples.Foo"/>
</beans>
ps:如果声明的属性以Ref为结尾,那么会引发引用冲突。
ps:p-namespace并不如标准xml格式灵活。
ps:建议在使用p-namspace时,现在团队之中讨论,然后进行意见统一。
使用c-namespace的xml缩写
c-namespace的使用方法与p-namespace相同,使用构造器的参数的名称来设置值。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="bar" class="x.y.Bar"/>
<bean id="baz" class="x.y.Baz"/>
<!-- traditional declaration -->
<bean id="foo" class="x.y.Foo">
<constructor-arg ref="bar"/>
<constructor-arg ref="baz"/>
<constructor-arg value="[email protected]"/>
</bean>
<!-- c-namespace declaration -->
<bean id="foo" class="x.y.Foo" c:bar-ref="bar" c:baz-ref="baz" c:email="[email protected]"/>
</beans>
<bean id="foo" class="x.y.Foo" c:_0-ref="bar" c:_1-ref="baz"/>
ps:通过index来设置构造器参数。
ps:尽量在配置文件中只使用名称记号法。
复合属性名称
在设置属性时,可以使用复合属性或嵌套属性,只要路径中除了最终属性以外的所有组件都不为null。
<bean id="example" class="examples.Example">
<property name="aaa.bbb.ccc.ddd" value="123" />
</bean>
使用depends-on
depends-on属性可以显示强制一个或多个bean在当前bean被初始化之前初始化。
<bean id="example" class="examples.Example" depends-on="foo,fuz" />
<bean id="foo" class="examples.foo" />
<bean id="fuz" class="examples.fuz" />
ps:表示依赖多个bean时,可以使用逗号、空格或分号作为合法分隔符用以提供一组bean名称。
ps:depends-on属性除了可以控制对象的初始化顺序,还可以控制单例对象的销毁顺序,定义了depends-on属性的bean会先被销毁。
怠惰初始化beans
默认情况下,ApplicationContext会将创建配置所有单例beans作为初始化过程的一部分。
这种预初始化可以是配置错误与环境错误迅速找出。
可以通过将bean标识为怠惰初始化来阻止其预初始化过程。
怠惰初始化bean会告知IoC容器在bean 实例被第一次调用时才进行初始化,而不是在容器启动时初始化。
<bean id="example" class="examples.Example" lazy-init="true" />
ps:当一个怠惰初始化的bean被一个单例预初始化bean依赖时,怠惰初始化bean会在容器启动时被创建,然后注入预初始化bean中。
可以在容器级别开启怠惰初始化
<beans default-lazy-init="true">
</beans>