Spring中的bean

Posted 云中之歌

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring中的bean相关的知识,希望对你有一定的参考价值。

1.定义和别名

定义一个bean可以为其制定如下属性

default-lazy-init:延迟初始化(默认false,即立即初始化)

default-merge:从父类合并继承属性值

default-autowire:可以按byName,byType等方式完成自动装配

default-autowire-candidates:自动装配时候排除此bean

bean可以使用id定义唯一名字,还可以使用name定义别名,例如<bean id="person" name="#abc,@123" />

还可以使用<alias>标签定义别名,例如<alias name="person" alias="jack" />

2.bean作用域

使用scope属性可以指定bean作用域,例如<bean id="person" class="spi.Person" scope="singleton" />

默认作用域为 singleton,即单例,可重复使用,也可以指定为prototype,每次使用bean时Spring都重新new出一个实例。

此外还有三种web中的作用域,分别是request (每个HTTP请求都创建一个新bean),session(每个HTTP session使用同一个bean),global session全局的HTTP session对应一个bean实例

3.设置普通属性值

使用value属性或者<value>标签可以为bean设置普通属性值,Spring自动判断数据类型,例如

1 <bean id="person" class="spi.Person">
2     <!-- 使用value属性设置普通属性值,这里是int类型-->
3   <property name="personId" value="1">
4     <!--使用嵌套 value 标签的方式设置普通属性值,这里是double类型 -->
5   <property name="high">
6     <value>1.76</value>
7   </property>
8 </bean>

 

4.自动装配

如果指定了bena的autowire属性可以进行自动装配

如果在<beans>标签添加default-autowire属性,将对所有<bean>起作用,如果在<bean>标签添加autowire(注意这里不是default-autowire),则只对单个bean起作用。

autowire支持no, byName, byTye, constructor, autoetect值。

byName: 根据bean中setter方法的名称,去容器中查找对应的bean,例如Person类中有一个setter方法叫做 setSchool(), 那么就在容器中查找<bean id="school" ../>,找得到就进行注入。

 1 class Person {
 2     School school;
 3     public setSchool(School school) {
 4         this.school = school;
 5     }
 6 }
 7 
 8 class School {
 9     String schoolName;
10 }

 

 

1 <bean id="person" class="Person" autowire="byName" />
2 <bean id="school" class="School" />

 

byType: 根据bean中setter方法的参数类型查找,还是上面的例子,Person的setSchool()方法需要一个School类型的参数,Spring就会在容器中查找类型为School的bean。配置如下。

1 <bean id="person" class="Person" autowire="byType" />
2 <bean id="school" class="School" />

 

类似的,constructor会根据构造函数的参数类型,在容器中查找对应的bean

注意的是,对于byType和constructor两种自动装配, 在容器中查找对应的bean不能超过一个,否则Spring无法决定装配哪一个。

例如上面的例子,假如有第三个bean继承自School,叫做HighSchool,容器中配置了<bean id="highSchool" class="HighSchool" />,那么Spring就不知道要装配哪一个给Person了。

autodetect: 由容器自行决定自动装配策略。如果找到默认构造函数,则使用byTpye策略。

自动装配可以减少配置代码量,但是会增加不透明性,对于大型项目不推荐自动装配。

5.注入嵌套bean

<bean>中嵌套一个bean,嵌套的bean只能用来注入,其本质与ref注入是一样的,区别是嵌套的bean不能被容器访问,因此也不再需要id属性,例如下面,

1 <bean id="person" class="Person">
2   <property name="school">
3     <bean class="School">
4   </property>
5 </bean>

 

6.注入集合值

如果类中定义了list, set, map, properties, array等集合属性,在bean中要为集合属性注入值时,可以在<property>标签下面嵌套<list>, <set> , <map> , <props> 等标签为其注入值。

下面是一个为集合属性注入值的例子,假如有如下类(bean),

1 public class CollectionBean {
2     private List<String> schools;
3     private Map scores;
4     private Map<String, Axe> phaseAxes;
5     private Properties health;
6     private Set axes;
7     private String[] books;
8 ...
9 }

 

则对应的XML配置如下,

 1     <bean id="collectionBean" class="CollectionBean">
 2         <!-- 为schools注入list集合类型的值 -->
 3         <property name="schools">
 4             <list>
 5                 <value>小学</value>
 6                 <value>中学</value>
 7             </list>
 8         </property>
 9         
10         <!-- 为scores注入map集合类型的值 -->
11         <property name="scores">
12             <map>
13                 <entry key="语文" value="89" />
14                 <entry key="数学" value="88" />
15             </map>
16         </property>
17         
18         <!-- 为phaseAxe注入map集合类型的值,key为String类型,value为Axe类型 ,复合类型的值使用value-ref进行引用-->
19         <property name="phaseAxe">
20             <map>
21                 <entry key="原始社会" value-ref="stoneAxe" />
22                 <entry key="农业社会" value-ref="steelAxe" />
23             </map>
24         </property>
25         
26         <!-- 为health注入properties集合类型的值 -->
27         <property name="health">
28             <props>
29                 <prop key="血压">正常</prop>
30                 <prop key="身高">175</prop>
31             </props>
32         </property>
33         
34         <!-- 为axes注入set集合类型的值 -->
35         <property name="axes">
36             <set>
37                 <!-- 每个value,ref,bean..都可以配置一个set元素 -->
38                 <value>普通字符串</value>
39                 <ref bean="stoneAxe" />
40                 <bean id="steelAxe" class="spi.SteelAxe" />
41                 <!-- 为set集合配置一个list集合作为一个元素 -->
42                 <list>
43                     <value>20</value>
44                     <!-- 再次为list集合配置一个set集合作为元素 -->
45                     <set>
46                         <value type="int">30</value>
47                     </set>
48                 </list>
49             </set>
50         </property>
51         
52         <!-- 为books注入一个数组值 -->
53         <property name="books">
54             <!-- 数组和list使用一样的注入方法 -->
55             <list>
56                 <value>语文</value>
57                 <value>英语</value>
58             </list>
59         </property>
60     </bean>

 

7.注入组合属性

假如有一个类Person中有一个属性为School school,这里的school也是一个类对象,也包含属性,而相对于Person的对象来说,school对象的属性就是组合属性。

1 class Person {
2     School school = new School();
3 }
4 
5 class School {
6     String schoolName;
7 }

 

如果我们现在需要为组合数学注入值,那么在XML中的配置如下,

1 <bean id="person" class="Person">
2   <property name="person.schoolName" value="北京大学" />
3 </bean>

 

为组合属性注入值要注意两点,

一是组合属性对应的对象不能为空,例如上面的school对象,必须初始化。

二是组合属性除了最后一段可以为null,其他都不能,否则会出现空指针异常。例如假如有foo.bar.name,则name可以为null,bar和foo都不可以为null

 

以上是关于Spring中的bean的主要内容,如果未能解决你的问题,请参考以下文章

死磕 Spring----- IOC 之从单例缓存中获取单例 bean

[死磕 Spring 17/43] --- IOC 之从单例缓存中获取单例 bean

Bean后置处理器 - BeanPostProcessor#postProcessAfterInitialization

如何获取容器中的bean对象

BeanDefinitionRegistryPostProcessor自定义替换spring中的bean

BeanDefinitionRegistryPostProcessor自定义替换spring中的bean