`
足至迹留
  • 浏览: 495767 次
  • 性别: Icon_minigender_1
  • 来自: OnePiece
社区版块
存档分类
最新评论

<2> 基本bean装配

阅读更多
本篇只介绍基本的最常用的bean装配知识,高级装配在下篇简要梳理。

在spring中,组件无需自己负责与其他组件的关联,取而代之的是,容器负责把协作组件的引用给予各个组件。创建系统组件之间协作关系的动作是DI的关键,通常被称之为装配。

Spring容器是Spring框架的核心,容器可以创建组件,装配和配置组件,以及管理他们的生命周期(从new()到finalize())。
Spring提供了多种容器实现,并分为两类。一类是Bean工厂(BeanFactory),最简单的容器,提供了基础的依赖注入支持。一类是应用上下文(ApplicationContext),建立在Bean工厂基础之上,提供了系统架构服务,如从属性文件中读取文本信息,向相关的事件监听器发布事件(这两点在下篇bean的高级装配中都会有)。

Spring中有几种BeanFactory的实现,用的最多的是XmlBeanFactory。要使用XmlBeanFactory需要传递一个org.srpringframework.core.io.Resource实例给构造函数,此Resource对象提供xml文件给容器。Spring提供的Resource有下面几种:



如:
BeanFactory factory = new XmlBeanFactory(new FileSystemResource(“c:/bean.xml”));
这行简单的代码告诉Bean工厂从xml文件中读取Bean的定义信息,但是,现在工厂还没有实例化Bean,Bean工厂是延迟加载bean的,只有在需要的时候才加载(后面会看到应用上下文会预加载singleton的bean,除非bean被声明了lazy-init=”true” 或abstract=”true”)。
为了从BeanFactory得到一个Bean,只要简单的调用getBean()方法,把bean的名字当参数传递进去就行了。
MyBean bean = (MyBean)factory.getBean(“myBeanName”);
当调用getBean()方法时,工厂才会实例化Bean,并且使用依赖注入设置bean的属性,这样就在Spring容器中开始了Bean的生命。

由于应用上下文提供了更强的功能,几乎所有的应用系统都选择ApplicationContext而不是BeanFactory.只在资源很少的情况下才会考虑采用BeanFactory,如移动设备上。
在ApplicationContext的诸多实现中,有三个实现经常用到:
1)ClassPathXmlApplicationContext,从类路径中的xml文件载入上下文定义信息。
2)FileSystemXmlApplicationContext, 从文件系统中的xml文件载入上下文信息。
3)XmlWebApplicationContext,从web系统中的xml文件载入上下文信息。

使用举例:
ApplicationContext ctx = new ClassPathXmlApplicationContext(“applicationContext.xml”);

ApplicationContext ctx = new FileSystemXmlApplicationContext(“c:/applicationContext.xml”);
两者区别是FileSystemXmlApplicationContext只能在指定的路径中寻找applicationContext.xml文件,而ClassPathXmlApplicationContext可以在整个类路径(包括jar文件)中寻找xml文件。
然后可以向BeanFactory一样通过getBean()获取bean,因为ApplicationContext接口扩展自BeanFactory接口。
应用上下文和bean工厂的另一个重要区别是:Bean工厂延迟加载所有的bean,直到getBean()被调用才创建bean,而应用上下文启动后会预载入所有的单实例bean, 除非bean被声明了lazy-init=”true” 或abstract=”true”.

下图是Bean在BeanFactory中的生命周期:



Bean在应用上下文中的生命周期跟上面只有一点不同:



唯一的不同是,如果bean实现了ApplicationContextAware接口,setApplicationContext()方法会被调用。

在xml中声明bean.
<bean id=”duke” class=”com.spring.Juggler” />
<bean>元素是Spring中最基本的配置单元,它通知spring创建一个bean对象。当spring容器装载该bean时,将用默认的构造函数实例化。
其中,id属性定义了该bean的名称,class属性指明了bean的类型。还可以定义:
<bean name=”duke” class=”com.spring.Juggler” />

注:bean的id和name的区别
1)id必须符合xml命名规范,不能以数字,符号开头,不能有空格。name无限制。
2)id不能有重复,否则初始化会报错,name可以重复,后面的会覆盖前面的。
3)name可以用逗号(,)隔开,每个名称都可用,如:
   <bean name=”aa,bb,cc” class=”…”  />
   则:getBean(“aa”); 或getBean(“bb”);或getBean(“cc”)都一样。
4)id和name都不指定,则以类全名为name.如果有多个不指定name和id的匿名bean,且类名一样,如:
<bean class=”com.spring.Test” />
<bean class=”com.spring.Test” />
<bean class=”com.spring.Test” />
则:getBean(“com.spring.Test”);取的是第一个,
getBean(“com.spring.Test#1”);取的是第二个,
getBean(“com.spring.Test#2”);取的是第三个。
综上:建议使用id,不要使用name.


Bean的属性注入方式:
1. 构造函数注入(使用constructor-arg)
如:
<bean id=”aa” class=”…”>
  <constructor-arg  value=”15” />  ----int型的15,基本类型可以自己转换,使用value设置。
  <constructor-arg  value=”string-15” /> ----string类型的15,基本类型可以自己转换,使用value设置。
<constructor-arg  ref=”otherbean” /> ----使用ref引用其他定义好的bean.
</bean>

注:与ref类似还可以使用idref属性来指定要引用的bean的名称,但两者完全不一样,idref提供的是类似value的功能,只是引用的普通字符串,但是有校验功能,而ref是引用的真实的bean,但idref比value多了验证功能。此外,idref和ref都有三个属性,分别是parent,local和bean。
还可以参考:http://taoyang168.blog.163.com/blog/static/126505069201232533626413/

有些时候,容器在加载XML配置的时候,因为某些原因,无法明确配置项与对象的构造方法参数列表的一一对应关系,就需要 请<constructor-arg>的type或者index属性出马。比如,对象存在多个构造方法,当参数列表数目相同而类型不同的时 候,容器无法区分应该使用哪个构造方法来实例化对象,或者构造方法可能同时传入最少两个类型相同的对象。
如:
<bean id="mockBO" class="..MockBusinessObject">
<constructor-arg type="int">
    <value>111111</value>
</constructor-arg>
</bean>

<bean id="mockBO" class="..MockBusinessObject">
<constructor-arg index="0" value="11111"/>
<constructor-arg index="1" value="22222"/>
</bean>

2. setter注入
如:
<bean id=”aa” class=”…” >
<property name=”song” value=”lalala” />
<property name=”instrument” ref=”piano” />
</bean>
注:Spring容器返回bean实例的过程:初始化主调bean->初始化依赖bean->将依赖bean注入到主调bean中->返回完整的主调bean实例。
还可以参考:http://blog.csdn.net/jbuilder3/article/details/5413300

注入内部bean:
<bean id=”aa” class=”…” >
<property name=”song” value=”lalala” />
<property name=”instrument”>
<bean class=”org.srping.Saxophone” />
    </property>
</bean>
内部bean也可以在构造函数注入方式中使用。内部bean只能用来注入,不能用来被其他bean引用。

3. 工厂方法注入(factory-method,允许使用指定的static方法来创建实例而不是使用构造函数)
在后面高级bean装配时会介绍。
还可以参考:
http://blog.sina.com.cn/s/blog_5f1fe33f0100hyx7.html
http://www.360doc.com/content/07/0327/13/18042_416050.shtml

装配集合
前面介绍了基本属性(通过value)和其他类(通过ref),但value和ref只有在属性是单一的时候才有效,当属性是复数(就是集合)时spring提供了4个类型的集合配置元素
<list> 装配一列值,允许重复
<set> 装配值集,确保无重复
<map> 装配键值对的集合,名称和值可以是任意类型
<props> 装配键值对的集合,名称和值都是string类型
<list>和<set>可以不经修改而使用任何collection上,两个元素可以与任意类型java.util.Collection中的属性交换。
如:
<property name=”instruments”>
<list>
    <value>第一个元素</value>
    <ref bean=”guitar” />
<ref bean=”cymbal” />
<ref bean=”harmonica” />
</list>
</property>
<list>可以用在以下代码上照常工作:
java.util.List<Instrument> instruments;  或者
Instruments[ ] instruments; 或者
Collection<Instrument> instruments;

可以在用到<list>的地方换成<set>,区别是<set>可以保证元素唯一。即使配置了重复元素,使用时仍是保持无重复的元素存在。

<property name=”instruments”>
<map>
    <entry key=”guitar” value-ref=”guitar” />
<entry key=”cymbal” value-ref=”cymbal” />
</map>
</property>
每个entry有两个属性,一个是key,另一个是value.分别有两个属性可以用:
key 指定map的键为string
key-ref 指定键为其他bean的引用
value 指定map的值为string
value-ref 指定map的值为其他bean的引用

<property name=”instruments”>
<props>
    <prop key=”guitar”>I am guitar.</prop>
<prop key=”cymbal”>I am cymbal.</prop>
</props>
</property>

还可以显式的给属性装配null值.如:
<property name=”properynull”><null/></property>
区别:
bean.setMail(“”)  -> <value></value>
bean.setMail(null)  -> <value><null/></value>

自动装配的4种方式:
1) byName 在容器中寻找和需要自动装配的属性名相同的bean,如果没找到则没有被装配上。
2) byType 在容器中寻找一个与需要自动装配的属性类型相同(子类型可以自动向上转型为父类型)的bean,如果没找到则没有被装配。如果找到超过一个类型相同的bean,则会抛出UnsatisfiedDependencyException异常。
3) constructor 在容器中查找与需要自动装配的bean的构造函数参数一致的一个或多个bean,如果窜在不确定的bean或构造函数,则抛出UnsatisfiedDependencyException异常。
4) autodetect 首先尝试使用constructor来自动装配,然后使用byType方式。

如下的配置
<bean id=”kenny” class=”…” >
<property name=”song” value=”Jingle” />
<property name=”instrument” ref=”saxophone” />
</bean>
可以使用自动装配的写法:
<bean id=”instrument” class=”com.Instrument” />
<bean id=”kenny” class=”…” autowire=”byName”>
<property name=”song” value=”Jingle” />
</bean>

Spring的bean有一个autowire的属性,它可以为以下的6个值:
1、No:即不启用自动装配。Autowire默认的值。 
2、 byName: 通过属性的名字的方式查找JavaBean依赖的对象并为其注入。比如说类Computer有个属性printer,指定其autowire属性为 byName后,Spring IoC容器会在配置文件中查找id/name属性为printer的bean,然后使用Seter方法为其注入。 
3、 byType: 通过属性的类型查找JavaBean依赖的对象并为其注入。比如类Computer有个属性printer,类型为Printer,那么,指定其 autowire属性为byType后,Spring IoC容器会查找Class属性为Printer的bean,使用Seter方法为其注入。 
4、 constructor:通byType一样,也是通过类型查找依赖对象。与byType的区别在于它不是使用Seter方法注入,而是使用构造子注入。 
5、 autodetect:在byType和constructor之间自动的选择注入方式。 
6、 default:由上级标签<beans>的default-autowire属性确定 

一般都是使用byName。
注:自动装配可以减少配置xml,但最大的缺点就是缺乏透明,隐藏了很多细节。建议使用手动装配。
使用<property>和<constructor-arg>配置总会覆盖自动装配的bean。

关于注解Autowired和Resource的作用和区别,源码级分析非常好:
http://www.iflym.com/index.php/code/201211070001.html

Bean的范围(scope)



Bean的初始化和销毁

在spring 容器初始化 bean 和销毁前所做的操作定义方式有三种:
第一种:通过@PostConstruct 和 @PreDestroy 方法实现初始化之后和销毁bean之前进行的操作。这是一种注解的写法。
第二种是:通过 在xml的bean定义中使用init-method 和  destory-method方法。还可以在<beans>的顶层配置中使用default-init-method和default-destroy-method来指定一个上下文定义文件中所有bean的初始化方法和销毁方法。
如:<bean id="personService" class="com..beanscope.PersonService" scope="singleton"  init-method="init"  destroy-method="cleanUp" /> 
注:非singleton的bean即使指定destroy-method也不会执行,对于prototype类型的bean一旦bean生成之后,spring容器就不管它的消亡了。
第三种是: 通过java bean实现InitializingBean和 DisposableBean接口,要分别实现afterPropertiesSet()方法和destroy()方法。这种通过实现接口的方式与spring框架存在耦合性,建议使用前两种方式。
这三种方式如果同时存在,则一个bean初始化执行顺序是:
Bean的构造函数Construct->@PostConstruct->InitializingBean->init-method.

可以使用init-method和destroy-method属性来指定bean初始化和销毁要做的动作。

此外,上面所有的xml配置都可以使用注解来完成,可以参考:
http://developer.51cto.com/art/201104/255395.htm

  • 大小: 115.7 KB
  • 大小: 246.9 KB
  • 大小: 227.6 KB
  • 大小: 112.4 KB
分享到:
评论

相关推荐

    Spring中集合类型的装配

    &lt;ref bean="bean2"/&gt; &lt;value&gt;stringValue&lt;/value&gt; &lt;/list&gt; &lt;/property&gt; &lt;/bean&gt; &lt;bean id="bean1" class="com.example.Bean1"/&gt; &lt;bean id="bean2" class="com.example.Bean2"/&gt; ``` 在上述代码中,`myList`...

    Spring+Mybatis+BoneCP配置实例

    &lt;bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"&gt; &lt;property name="dataSource" ref="dataSource"/&gt; &lt;property name="configLocation" value="classpath:mybatis-config.xml"/&gt; ...

    spring bean 属性总结

    例如,`&lt;bean name="bean1, bean2" class="com.example.MyClass"&gt;`。 - **singleton属性**:决定Bean是否为单例模式。当设置为`true`时,整个应用中只有一个Bean实例;设置为`false`时,每次请求都会创建一个新的...

    Spring In Action笔记100例

    &lt;value&gt;value2&lt;/value&gt; &lt;/list&gt; ``` - **`&lt;set&gt;`**: 用于创建集合资格。与`&lt;list&gt;`类似,但不允许重复元素。同样使用`&lt;value&gt;`标签添加元素。例如: ```xml &lt;set&gt; &lt;value&gt;value1&lt;/value&gt; &lt;value&gt;value2&lt;/...

    火炬博客系统7

    &lt;br&gt; Spring框架是轻量级组件部署和运行的容器,可以很好的支持AOP(面向切面编程)的开发模式,Spring能有效地组织中间层对象,通过Bean容器为业务对象、DAO对象和资源对象提供了IOC类型的装配能力,将Struts和...

    火炬博客系统6

    &lt;br&gt; Spring框架是轻量级组件部署和运行的容器,可以很好的支持AOP(面向切面编程)的开发模式,Spring能有效地组织中间层对象,通过Bean容器为业务对象、DAO对象和资源对象提供了IOC类型的装配能力,将Struts和...

    Spring总结.txt

    这里通过`&lt;property&gt;`标签设置了`Person`类的`name`和`age`属性,并通过`&lt;ref&gt;`标签引用了之前定义的`car`和`car2`两个Bean。 ##### 2. 使用集合类型配置Bean属性 - **List集合**:可以通过`&lt;list&gt;`标签来配置一...

    火炬博客系统5

    &lt;br&gt; Spring框架是轻量级组件部署和运行的容器,可以很好的支持AOP(面向切面编程)的开发模式,Spring能有效地组织中间层对象,通过Bean容器为业务对象、DAO对象和资源对象提供了IOC类型的装配能力,将Struts和...

    spring bean XML配置入门

    在本文中,我们将深入探讨Spring框架中的Bean XML配置,这是Spring的核心特性之一,它允许我们定义、管理和装配应用中的对象。我们将围绕以下知识点展开: 1. **Spring框架基础**: Spring是一个开源的Java平台,...

    spring代码3

    &lt;value&gt;Value2&lt;/value&gt; &lt;ref bean="anotherBean"/&gt; &lt;/list&gt; &lt;/constructor-arg&gt; &lt;/bean&gt; ``` - **Set装配**:类似地,使用`&lt;set&gt;`标签声明一个集合,元素可以通过`&lt;value&gt;`或`&lt;ref&gt;`定义。 - **Map装配**:...

    Spring的Bean配置说明

    - **`no`**:不使用自动装配,Bean的所有依赖项都需要显式地通过`&lt;ref&gt;`或`&lt;value&gt;`配置。 - **`byName`**:根据属性名称进行自动装配,Spring会尝试将名称匹配的Bean注入到相应的位置。 - **`byType`**:根据...

    Spring学习之Bean的装配多种方法

    School Bean有四个属性:name、location、teachers和buildings,我们使用 `&lt;property&gt;` 元素来注入对应的值,其中location属性使用 `&lt;ref&gt;` 元素来注入Location Bean,teachers和buildings属性使用 `&lt;list&gt;` 和 `...

    Spring环境搭建

    - 使用`&lt;ref&gt;`标签:如`&lt;property name="Bean4"&gt;&lt;ref bean="Bean4"/&gt;&lt;/property&gt;` - 使用内部`&lt;bean&gt;`定义:如`&lt;property name="Bean4"&gt;&lt;bean class="com.example.Bean4"/&gt;&lt;/property&gt;` 对于共享属性的bean,可以...

    spring2.5学习笔记

    &lt;value&gt;list2&lt;/value&gt; &lt;/list&gt; &lt;/property&gt; &lt;!-- ...其他字段的注入配置... --&gt; &lt;/bean&gt; ``` 以上就是Spring框架中关于Ioc、AOP、事务管理和属性注入的基本知识,它们是构建高效、松耦合的企业级应用的基础。...

    Spring AOP配置实例

    &lt;bean id="loggingAspect" class="com.example.aspect.LoggingAspect" /&gt; ``` 或者在Java配置中: ```java @Bean public LoggingAspect loggingAspect() { return new LoggingAspect(); } ``` 通过以上...

    ssi框架搭建流程

    &lt;filter-name&gt;Struts2&lt;/filter-name&gt; &lt;filter-class&gt;org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter&lt;/filter-class&gt; &lt;/filter&gt; &lt;filter-mapping&gt; &lt;filter-name&gt;Struts2&lt;/filter-name&gt;...

    spring资料d1.rar

    一个基本的Spring配置文件通常包含`&lt;beans&gt;`根元素,以及在其中声明的多个`&lt;bean&gt;`元素。每个`&lt;bean&gt;`元素代表一个Java对象,其`id`属性用于唯一标识该Bean,`class`属性指定对应的类名。例如: ```xml &lt;beans&gt; ...

    ssm复习题 (1) (1).doc

    - @Autowired:自动装配bean,根据类型或名称来自动装配依赖。 - @Repository:标记为数据访问组件,主要用于DAO层,Spring会自动为其提供事务管理。 - @Service:表示业务逻辑组件,通常用在服务层。 - @...

    spring总结

    &lt;prop key="prop2"&gt;value2&lt;/prop&gt; &lt;/props&gt; &lt;/property&gt; &lt;/bean&gt; ``` ### 使用ApplicationContext - **监听器配置**:为了减少每次请求都创建新的`ApplicationContext`实例带来的开销,可以通过配置监听器...

    面试官常问的spring依赖注入和bean的装配问题.pdf

    总结来说,Spring框架的依赖注入和Bean装配是面试中的热点问题,掌握它们对于每一个Spring开发者来说都是基本要求。无论是使用Spring框架还是Spring Boot,理解依赖注入的机制和装配方法,都是构建高质量Spring应用...

Global site tag (gtag.js) - Google Analytics