Spring——装配Bean
Posted KLeonard
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring——装配Bean相关的知识,希望对你有一定的参考价值。
基本装配
在Spring容器内拼凑Bean叫做装配。装配Bean的时候,需要告诉哪些Bean以及容器如何使用依赖注入将它们配合在一起。
使用XML装配
XML是最常见的Spring应用系统配置源。
几种Spring容器都支持使用XML装配Bean,包括:
XmlBeanFactory:调用ClassPathResource载入上下文定义文件(比如applicationContext.xml)。
ClassPathXmlApplicationContext:从类路径载入上下文定义文件。
XmlWebApplicationContext:从Web应用上下文中载入定义文件。
配置文件举例如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="student" class="com.gavin.ioc.Student" scope="singleton">
<property name="name" value="Gavin"/>
</bean>
</beans>
- 上下文定义文件的根元素是beans,有多个bean子元素。每个bean元素定义了一个bean如何被装配到Spring容器中。
- 对bean的最基本的配置包括bean的ID和bean的全称类名。
scope
几种scope属性值:prototype
、singleton
、request
、session
、global-session
。Spring中的bean缺省情况下是单例模式。始终返回一个实例。若想返回不同的实例的话需要定义成原型模式。
作用域 | 描述 |
---|---|
singleton | 在每个Spring IoC 容器中一个Bean定义对应一个对象实例 |
prototype | 一个Bean定义对应多个实例 |
request | 在一个HTTP请求中,一个Bean定义对应一个对象实例;即每次HTTP请求都将会有各自的Bean实例,它们依据某个Bean定义创建而成。该作用域仅在基于Web的Spring Application情形下有效。 |
session | 在一个HTTP Session中,一个Bean定义对应一个对象实例。该作用域仅在基于Web的Spring Application情形下有效。 |
global-session | 在一个全局的HTTP Session中,一个Bean定义对应一个对象实例。典型情况下,仅在使用portlet context的时候有效。该作用域仅在基于Web的Spring Application情形下有效。 |
使用原型Bean会对性能产生影响,尽量不要设置为prototype,除非有必要。
实例化与销毁
Spring实例化bean或销毁bean时,有时需要做一些处理工作,因此Spring可以在创建和拆卸bean的时候调用bean的两个生命周期方法,即init-method
方法和destory-method
方法
Spring也提供了两个接口来实现相同的功能:InitializingBean
和DisposableBean
。InitializingBean
接口提供了一个afterPropertiesSet()
方法。DisposableBean
接口提供了destroy()
方法。
但是不推荐使用这两个接口,它会把Bean与Spring API绑定在一起。
通过set方法注入依赖
bean元素的property子元素指明了使用它们的set方法来注入。可以注入任何东西,从基本类型到集合类,甚至是应用系统的Bean。
内部Bean
在property内部配置一个Bean,那么这个Bean只能被该属性引用。而不能被其他属性引用。
<bean id="outside" class="...">
<property name="emp">
<bean id="inside" class="...">
<property name="" value=""/>
</bean>
</property>
</bean>
如上例所示,emp属性引用inside这个Bean,这里inside这个Bean只能被该emp属性引用,其他属性是不能引用的。
继承配置
Graduate类继承Student类,属性如下:
public class Student
protected int age;
protected String name;
...
public class Graduate extends Student
private String degree;
...
配置如下:
<!--配置一个学生-->
<bean id="student" class="com.gavin.inherit.Student">
<property name="age" value="18"/>
<property name="name" value="Gavin"/>
</bean>
<bean id="graduate" parent="student" class="com.gavin.inherit.Graduate">
<!--如果单独再配置name和age,则会覆盖从父对象继承的这个属性的值-->
<property name="age" value="20"/>
<property name="name" value="XiaoMing"/>
<property name="degree" value="学士"/>
</bean>
给集合属性注入值
给数组或List集合注入值的配置方式如下:
Department有三个属性:
private String name;
private String[] empName;
private List employeeList;
<property name="empName">
<list>
<value>小明</value>
<value>小红</value>
<value>小亮</value>
</list>
</property>
<property name="employeeList">
<list>
<ref bean="employee"/>
<ref bean="employee1"/>
<ref bean="employee2"/>
</list>
</property>
给Set集合的注入与此类似:
<property name="employeeSet">
<set>
<ref bean="employee"/>
<ref bean="employee1"/>
<ref bean="employee2"/>
<ref bean="employee2"/>
<ref bean="employee2"/>
</set>
</property>
给Map属性注入值
Map的注入也是类似的,不过稍有复杂而已:
Department中增加Map属性:
private Map employeeMap;
Spring中配置如下:
<property name="employeeMap">
<map>
<entry key="1" value-ref="employee"/>
<entry key="2" value-ref="employee1"/>
<entry key="3" value-ref="employee2"/>
</map>
</property>
注入空值
<property name="barlist">
<null/>
</property>
通过构造函数注入依赖
Employee对象如下:
public class Employee
private String name;
private int age;
public Employee()
public Employee(String name, int age)
System.out.println("Employee(String name, int age)函数被调用");
this.name = name;
this.age = age;
public Employee(String name)
System.out.println("Employee(String name)函数被调用");
this.name = name;
配置文件:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--配置一个Employee对象-->
<bean id="employee" class="com.gavin.constructor.Employee">
<!--通过构造函数来注入-->
<constructor-arg index="0" value="Gavin"/>
<constructor-arg index="1" value="19"/>
</bean>
</beans>
也就是说,可以通过在bean元素下,配置constructor-arg元素来给构造函数传递参数。index用于指定参数的位置。
set注入的缺点是无法清晰表达哪些属性是必须的,哪些是可选的,构造注入的优势是通过构造强制依赖关系,不可能实例化不完全的或无法使用的Bean。
如果属性是对象类型,则使用ref=”“
自动装配Bean的属性值
<bean id="foo" class="...Foo" autowire="autowire type">
有四种自动装配类型:
- byName:寻找和属性名相同的Bean,若找不到,则装不上。
- byType:寻找和属性类型相同的Bean,找不到,装不上,找到多个抛异常
- constructor:查找和bean的构造参数一致的一个或多个Bean,若找不到或找到多个,抛异常。按照参数的类型匹配。
- autodetect:(3)和(2)之间选一个方式。不确定性的处理与(3)和(2)一致。【3和2有先后顺序!】
- default:这个需要在beans中配置
default-autowire="指定"
。当在beans中指定了default-autowired之后,所有Bean的默认autowire方式就是该指定的装配方式。 no:不自动装配,这是autowire的默认值
- byName的案例:
public class Dog
private String name;
private int age;
...
public class Master
private String name;
private Dog dog;
...
Master中有Dog对象,配置如下:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--Master对象-->
<bean id="master" class="com.gavin.autowire.Master" autowire="byName">
<property name="name" value="Gavin"/>
</bean>
<!--Dog对象-->
<bean id="dog" class="com.gavin.autowire.Dog">
<property name="name" value="大黄"/>
<property name="age" value="2"/>
</bean>
</beans>
可以看到,master中并没有引用dog对象,而是设置了属性autowire=byName,这时Spring容器会根据属性名字寻找,找到属性名是dog的对象后,自动装配。
其他的也类似,比如byType是按照类型来寻找,那么不管Dog对象的属性名是什么,只要能找到一个Dog对象,就能自动装配。但是找到多个Dog对象就会抛出异常了。
- constructor的话,需要在Master中写一个只有Dog参数的构造方法,那么Spring容器会将配置的Dog对象传递给这个构造函数。
public class Master
private String name;
private Dog dog;
public Master(Dog dog)
this.dog = dog;
...
配置如下:
<bean id="master" class="com.gavin.autowire.Master" autowire="constructor">
<property name="name" value="Gavin"/>
</bean>
<!--Dog对象-->
<bean id="dog" class="com.gavin.autowire.Dog">
<property name="name" value="大黄"/>
<property name="age" value="2"/>
</bean>
【注意】:自动装配能不用就不用!因为自动装配没有set注入或者构造函数注入明确。
使用Spring特殊的Bean
让Spring特殊对待这些Bean,使它们可以:
1.通过配置后加工Bean,涉及到Bean和Bean工厂生命周期。(比如BeanPostProcessor等)
2.改变依赖注入,将字符串转换成其它类型
3.从属性文本装载信息,包括信息国际化
4.监听并处理其它Bean及Spring发布的系统消息
5.知道自己在Spring中的唯一标识。
以上是关于Spring——装配Bean的主要内容,如果未能解决你的问题,请参考以下文章