从本质上来看,Spring容器就是一个超大型工厂,Spring容器中的Bean就是该工厂的产品。Spring容器能产生哪些产品,则完全取决于开发者在配置文件中的配置。
<beans.../>元素是Spring配置文件的根元素,该元素可以指定如下属性:
属性名 | 说明 |
deafult-lazy-init | 指定该beans元素下配置的所有Bean默认的延迟初始化行为 |
default-merge | 指定该beans元素下配置的所有Bean默认的merge行为 |
default-autowire | 指定该beans元素下配置的所有Bean默认的自动装配行为 |
default-autowire-candidates | 指定该beans元素下配置的所有Bean默认是否作为自动装配的候选Bean |
default-init-method | 指定该beans元素下配置的所有Bean默认的初始化方法 |
default-destroy-method | 指定该beans元素下配置的所有Bean默认的回收方法 |
定义Bean时,通常需要指定两个属性:id和class。id属性在Spring容器中应该是唯一的,class属性不能是接口,必须是实现类。
Spring容器集中管理Bean的实例化,Bean实例可以通过BeanFactory的getBean(String beanid)方法得到,BeanFactory变成简单工厂模式里的工厂,程序只需要获取BeanFactory的引用,即可获得Spring容器管理全部实例的引用。程序不需要与具体实例的实现过程耦合。
大部分JavaEE应用里,应用在启动时,会自动创建Spring容器,组件之间直接以依赖注入的方式耦合,甚至无须主动访问Spring容器本身。
当我们在配置文件中通过<bean id=" xxx " class="lee.XxxClass"/>方法配置一个Bean时,要求该Bean实现类必须有一个无参数的构造器,因此Spring底层相当于调用了代码:
xxx=new lee.XxxClass( );
如果在配置文件中通过构造注入来创建Bean,譬如:
<bean id="bean1" class="lee.Test1"> <constructor-arg value="hello"/> <constructor-arg value="23"/> </bean>上面代码相当于让Spring调用如下代码:
bean1=new lee.Test1("hello","23");由于Spring本身提供了功能强大的类型转换机制,因此如果lee.Test1只包含了一个Test1(String,int)构造器,那么上面的配置相当于让Spring执行如下代码:
bean1=new lee.Test1("hello",23);这就有了一个问题,如果lee.Test1类既有Test1(String,String)构造器,又有Test1(String,int)构造器,那么上面的配置到底是让Spring执行哪些代码呢?答案是Test1(String,String)。因为此时的配置还不够明确,对于<constructor-arg value="23"/>,Spring只能解析出一个“23”字符串,它到底需要转换为哪种数据类型------从配置文件中看不出来,只能是根据lee.Test1的构造器来尝试转换。
除了可以为bean元素指定一个id属性外,还可以为bean元素指定name属性,用于为Bean实例指定别名。如果需要为Bean实例指定多个别名,可以在name属性中使用逗号、冒号或空格来分隔多个别名,后面通过任一别名即可访问该Bean实例。在一些极端情况下,程序无法在定义Bean时就指定所有的别名,而是需要在其他地方为一个已经存在的Bean实例指定别名,则可使用<alias.../>元素来完成,该元素可指定如下两个属性:
① name:该属性指定一个Bean实例的标识名,表明将为该Bean实例指定别名。
② alias:指定一个别名。
<alias name="person" alias="jack"/> <alias name="jack" alias="jackee"/>在默认情况下,当Spring创建ApplicationContext容器时,Spring会自动预初始化容器中所有的singleton实例,如果我们不想让Spring容器预初始化某个singleton Bean,则可为该<bean.../>元素增加lazy-init属性,指定该属性为true,则Spring不会预初始化该Bean实例:
<bean id="bean2" class="lee.Test2" lazy-init="true"/>