Spring学习6(3)
在spring配置文件中,用户不但可以将String,int等字面值注入Bean中,还可以将集合,Map等其他类型的数据注入Bean中,还可以注入其它定义的Bean。
字面值
字面值一般是指可用字符串表示的值,这些值可用<value>
元素标签进行注入。基本数据类型及其封装类,spring类等都可以采用字面值注入。
spring可以将字符串表示的字面值转化为相应类型的值,还允许用户注册自定义的编辑器来处理其他类型属性注入时的转换工作。
下列例子就是注入字面值:
<bean id="car_attr1" class="com.smart.Car">
<property name="maxSpeed">
<value>200</value>
</property>
<property name="brand">
<value><![CDATA[红旗&CA72]]></value>
</property>
</bean>
这里“brand”的属性值使用了一个xml的特殊标签<![CDATA[]]>
让xml认为其中的字符串是普通文本,防止这个字符串里可能有xml格式的字符串而造成影响。
xml的特殊字符有5个:"&","<",">",“ " ” ,“ ‘ "。我们可以采用如上述中的代码来消除隐形也可以使用xml中定义的转义序列来替代:
<
对应<
>
对应>
&
对应&
"
对应"
'
对应&aops;
引用其他Bean
Ioc容器会为Bean相互引用提供桥梁,下面我们在com.smart.attr中建立一个新的类:
package com.smart.attr;
import com.smart.Car;
public class Boss{
private Car car;
public void setCar(Car car) {
this.car = car;
}
}
我们可以在配置文件中通过<ref>
元素引用car Bean,如下:
<bean id = "car_attr2" class="com.smart.Car"></bean>
<bean id = "boss_attr1" class="com.smart.attr.Boss">
<property name="car">
<ref bean="car"></ref>
</property>
</bean>
<ref>
可以通过下面3个属性引用容器中其他的Bean:
- bean:同一容器或父容器
- local:同一配置文件
- parent:父容器
下面来通过一个例子来了解,在attr目录下创建bean1.xml,代码如下:
<!-- 在父容器中定义的car -->
<bean id="car_attr3" class="com.smart.Car">
<property name="brand" value="红旗CA72"/>
<property name="maxSpeed" value="200"/>
<property name="price" value="2000.00"/>
</bean>
创建beans2.xml,其中代码如下,它被子容器加载:
<!-- 这里的Bean和父容器的Bean具有同样的id -->
<bean id="car_attr3" class="com.smart.Car">
<property name="brand" value="吉利CT5"/>
<property name="maxSpeed" value="100"/>
<property name="price" value="1000"/>
</bean>
<bean id="boss_attr2" class="com.smart.attr.Boss">
<property name="car">
<ref parent="car_attr3"/>
</property>
</bean>
接下来我们对父子容器加载进行实现,在test.com.smart.attr中创建test类,代码如下:
package com.smart.attr;
import com.smart.Car;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
public class ContainBeanTest{
@Test
public void parent() {
ClassPathXmlApplicationContext pFactory = new ClassPathXmlApplicationContext(new String[]{"com/smart/attr/beans1.xml"});
ApplicationContext factory = new ClassPathXmlApplicationContext(new String[] {"com/smart/attr/beans2.xml"},pFactory);
Boss boss = (Boss)factory.getBean("boss_attr2");
assertNotNull(boss);
boss.getCar().introduce();
}
}
我们这里可以看到输出信息,输出的是父容器中定义的bean,把parent改为bean就会输出当前的这个bean,改成local会报错。
内部Bean
如果car Bean只是被boss Bean所引用则可以采用内部bean的方式。内部bean即是提供了id,name,scope属性也会被忽略,实例如下:
<bean id="boss" class="com.smart.attr.Boss">
<property name="car">
<bean class="com.smart.Car">
<property name="maxSpeed" value="200"/>
<property name="price" value="2000"/>
</bean>
</property>
</bean>
Null值
如果用户尝试直接用不写value的方式来注入属性是不能够注入一个null值的,它会被解析为一个空字符串,我们可以用<null/>
标签来注入null值:
<property name="brand"><null/></property>
级联属性
spring同样支持级联属性,我们可以在定义Boss时直接给出Car的属性值,不过首先对Boss进行改造,声明一个初始化对象:
private Car car = new Car();
}
注意这样是不影响其他的配置方法的。
我们创建一个新的配置文件:
<bean id="boss_attr3" class="com.smart.attr.Boss">
<property name="car.brand" value="吉利CT50"/>
</bean>
</beans>
集合类型属性
java.util包中的集合类型是最常用的数据结构类型,包括List,Set,Map等,spring为这些集合类的属性提供了专属标签。
List
list不光是只针对list对于一般可以用字面值来配置的类型的数组可以用同样的方法来配置。
首先为Boss添加一个List类型的成员变量:
import java.util.List;
private List favorites = new ArrayList();
public List getFavorites() {
return this.favorites;
}
public void setFavorites(List favorites) {
this.favorites = favorites;
}
而后在配置中加入:
<bean id="boss_attr4" class="com.smart.attr.Boss">
<property name="favorites">
<list>
<value>A</value>
<value>B</value>
</list>
</property>
</bean>
list属性既可以通过<value>
注入字符串,也可以通过<ref>
注入容器其他的Bean。
Set
如果使用set则基本同理于list
```xml
<bean id="boss_attr4" class="com.smart.attr.Boss">
<property name="favorites">
<set>
<value>A</value>
<value>B</value>
</set>
</property>
</bean>
Map
为Boss添加一个Map类型的成员属性:
private Map jobs = new HashMap();
public Map getJosb() {
return this.jobs;
}
public void setJobs(Map jobs) {
this.jobs = jobs;
}
在配置文件中通过以下方式提供配置:
<bean id="boss_attr5" class="com.smart.attr.Boss">
<property name="jobs">
<map>
<entry>
<key><value>AM</value></key>
<value>会见客户</value>
</entry>
<entry>
<key><value>PM</value></key>
<value>公司内部会议</value>
</entry>
</map>
</property>
</bean>
同理,如果键和值是对象,可以用<ref>
标签代替<value>
标签。
Properties
Properties可以看作一个特殊的Map但是其中的key和值都只能是字符串。我们为Bean添加相关成员变量:
private Properties mails = new Properties();
public Properties getMails() {
return this.mails;
}
public void setMails(Properties mails) {
this.mails = mails;
}
其配置片段如下:
<bean id="boss_attr6" class="com.smart.attr.Boss">
<property name="mails">
<props>
<prop key="jobMail">john-office@smart.com</prop>
<prop key="lifeMail">john-life@smart.com</prop>
</props>
</property>
</bean>
注意这里值的配置没有<value>
子元素标签。
强类型集合
配置方式如同非强类型
集合合并
Spring支持集合合并的功能,允许子<bean>
继承父<bean>
的同名属性集合,如下代码:
<bean id="parentBoss" abstract="true" class="com.smart.attr.Boss">
<property name="favorites">
<list>
<value>A</value>
<value>B</value>
<value>C</value>
</list>
</property>
</bean>
<bean id="childBoss" parent="parentBoss">
<property name="favorites">
<list merge="true">
<value>D</value>
<value>E</value>
</list>
</property>
</bean>
这里通过指定merge="true"让父子属性值进行合并从而让子Bean拥有了5个属性值。
简化配置
我们可以简化xml中配置的书写来避免写太多的配置,但是需要注意的是,对于一些特殊情况是不能用简化的。下面给出书上的一些例子:
注意这里简化后就不能使用<![CDATA[]]>
来处理xml特殊字符了,之恩采用转义字符的方式来处理。
注意这里<ref>
的简化不适用于<ref local>
和<ref parent>
。
除了上述简化,我们可以用p命名空间进一步简化配置格式,实例如下:
<bean id="car" class="XXX.Car">
<property name="brand" value="HongQi"/>
</bean>
等同于
<bean id="car" class="XXX.Car"
p:brand="HongQi"/>
</bean>
总结来说,对于字面值属性格式为:
p:<属性名>="XXX"
对于引用对象属性有:
p:<属性名>-ref="XXX"
自动装配
spring Ioc容器知道所有Bean的配置信息,反射机制还能知道实现类的结构信息,所以spring自然就可以进行自动装配。
<bean>
元素提供了一个指定自动装配类型的属性:autowire=“<自动装配类型>”
以下是4种自动装配类型:
- byName:根据名称自动匹配,如Boss有名为car的属性,如果容器中刚好有个名为car的Bean就会将其自动装配给Boss的car属性。
- byType:根据类型自动匹配,Boss有一个Car类型的属性,容器中有个Car类型的Bean,则就会自动装配。
- constructor:和byType类似不过是针对构造函数而言的
- autodetect:根据Bean的自省机制决定采用byType还是constructor。
类似于<bean>
的autowire
,<beans>
也有default-autowire
其默认为“no”,其它可选配置值同上述四个。