Spring4--在IoC容器中装配Bean
背景
本章的重点是介绍如何装配Bean。
1.Spring配置概述
Bean配置信息是Bean的元数据信息,它由四个方面组成:
(1)Bean的实现类;
(2)Bean的属性信息,如数据源的连接数、用户名、密码等;
(3)Bean的依赖关系,Spring根据依赖关系配置完成Bean之间的装配;
(4)Bean的行为配置,如生命周期范围及生命周期各过程的回调函数等。
Bean元数据信息在Spring容器中的内部对应物是由BeanDefinition形成的Bean注册表。
下面这张图描述了Spring容器、Bean配置信息、Bean实现类及应用程序之间的相互关系:
基于xml的配置,spring采用Schema格式。spring配置的Schema文件放置在各模块JAR文件内一个名为config的目录下。
2.依赖注入
(1)属性注入指通过setXxx()方法注入Bean的属性值或依赖对象。Spring只会检查Bean中是否有对应的Setter方法,至于
Bean中是否有对应的属性成员变更则不做要求。Spring配置文件中<property>元素所指定的属性名和Bean实现类的Setter
方法满足Sun JavaBean的属性命名规范:xxx的属性对应 setXxx()方法。JavaBean的变量的前两个字母要么全部大写,要
么全部小写。
(2)构造函数注入,它能保证一些必要的属性在Bean实例化就得到设置,确保Bean实例化后就可以使用。Spring容器能对构
造函数配置的Bean进行实例化的前提是,即构造函数入参引用的对象必须已经准备就绪。如果两个Bean都采用构造函数注入,
而且都通过构造函数入参引用对方,就会发生类似于线程死锁的循环依赖问题。解决办法是修改Bean的代码,将构造函数注入
方式调整为属性注入方式。
(3)工厂方法注入。Spring IoC容器以框架的方式提供工厂方法的功能,并以透明的方式开放给开发者,所以很少需要手工编写
基于工厂方法的类。
3.注入参数详解
(1)字面值,指可用字符串表示的值,这些值可以通过<value>元素标签进行注入。Spring容器在内部为字面值提供了编辑器,
它可以将以字符串表示的字面值转换为内部变量的相应类型。
如果配置文件中的注入值包括下面的特殊字符,可以采用<![CDATA[]]>特殊标签,将包含特殊字符的字符串封装起来,另一个
办法是使用xml转义序列表示特殊字符。
(2)引用其他Bean,<ref>元素可以通过下面3个属性引用容器中的其他Bean:
1.bean:通过该属性可以引用同一容器或父容器中的Bean;
2.local:通过该属性只能引用同一配置文件中定义的Bean;
3.parent:引用父容器中的Bean。
(3)内部Bean,没有名字,不能被其他Bean引用,只能在声明处为外部Bean提供实例注入。
(4)null值,必须使用专用的<null/>元素标签。
(5)级联属性。
(6)集合类型属性,List、Set、Map、Properties。可以通过util命名空间配置集合类型的Bean。
(7)简化配置方式:
字面值属性简化:
引用对象属性:<ref local="xxx">和<ref parent="xxx">没有对应的简化形式
使用P命名空间:为了简化xml文件的配置,越来越多的xml文件采用属性而子元素配置信息。通过<bean>元素属性的方式配置
Bean的属性。
对于字面值属性 p:<属性名>=“xxx” ; 对于引用对象的属性 p:<属性名>-ref="xxx"
由于p命名空间的属性名师可变的,所以p命名空间没有对应的Schema定义文件。
(8)自动装配,Spring IoC容器可以按照某种规则对容器中的Bean进行自动装配,而无须通过显式的方式进行依赖配置。<bean>
元素提供了一个指定自动装配类型的属性 autowire="<自动装配类型>"。Spring提供了四种自动装配类型:
<beans>元素标签中的default-autowire属性可以配置全局自动匹配,默认值为no,表示不启用自动装配。
在实际开发中,xml配置方式很少启用自动装配功能,而基于注解的配置方式默认采用byType自动装配策略。
4.方法注入
Spring IoC容器拥有复写Bean方法的能力,归功于CGLib类包。CGLib可以在运行期动态操作Class字节码,为Bean动态
创建子类或实现类。lookup方法注入使用范围,一般是希望通过一个singleton Bean 获取一个prototype Bean时使用。
方法替换,可以使用某个Bean的方法去替换另一个Bean的方法,具体怎么操作看书。
5.<bean>之间的关系
(1)继承,如果多个<bean>存在相同的配置信息,则Spring允许定义一个父<bean>,子<bean>将自动继承父<bean>的配置
信息。父<bean>声明为abstract="true",子<bean>用parent="xxx"指定父<bean>。
(2)依赖,使用<ref>元素标签建立对其他Bean的依赖关系。通过depends-on属性显式制定Bean前置依赖的Bean,前置依赖
Bean会在本Bean实例化之前创建好。
(3)引用,一个<bean>引用另一个<bean>的id属性值,目的是在运行期通过getBean(beanName)方法获取对应的Bean。通过
使用 <idref>元素标签,在容器启动时,Spring会检查引用关系的正确性,这样就可以提前发现错误。
6.整合多个配置文件
在启动Spring容器时,可以通过一个String数组指定这些配置文件,Spring还允许通过<import>将多个配置文件引入到一个文
件中,进行配置文件的集成。
7.Bean作用域
Bean作用域类型:
通过scppe="<作用域类型>" 来指定。还可以自定义Bean的作用域,不过这个比较少用。
(1)singleton,无状态或者状态不可变的类适合使用单例模式。
如果不希望容器在启动时提前实例化singleton的Bean,可以通过lazy-init属性进行控制。
(2)prototype,在默认情况下,Spring容器在启动时不实例化prototype的Bean。Spring容器将prototype的Bean交给调用者后,
就不再管理它的生命周期。
(3)其他三个是与Web应用环境相关的Bean作用域,在使用之前需要在Web容器中进行额外的配置。利用HTTP请求监听器
进行配置。
两个监听器的区别:
ServletContextListener负责监听Web容器启动和关闭的事件,ServletRequestListener监听HTTP请求事件,Web服务器接收
到的每一次请求都会通知该监听器。
(3)如果将Web相关作用域的Bean注入singleton或prototype的Bean中,我们需要是使用SpringAOP创建代理。
8.FactoryBean
通过实现该工厂类接口定制实例化Bean的逻辑,它隐藏了实例化一些复杂Bean的细节,给上层应用带来了便利。
9.基于注解的配置
(1)除了@Component外,Spring还提供了3个功能基本和@Component等效的注解,分别对应DAO、Service及Web层的Controller进行注解:
[email protected]:用于对Dao实现类进行标注。
[email protected]:用于对Service实现类进行标注。
[email protected]:用于对Controller实现类进行标注。
(2)扫描注解定义的Bean,Spring提供了一个context命名空间,它提供了通过扫描类包以应用注解定义Bean的方式。也可以
通过contex定义过滤的规则,把不要的类过滤掉。
(3)自动装配Bean,使用@Autowired进行自动注入。@Autowired默认按类型(byType)配置的方式在容器中查找匹配的Bean。
在对类方法进行标注时,Spring将自动选择匹配入参类型Bean进行注入。建议在方法上标注@Autowired注解,在单元测试时就
比较方便。
10.基于java类的配置
普通的pojo只要标注@Configuration注解,就可以为Spring容器提供Bean定义的信息,每个标注了@Bean的类方法都相当于
提供了一个Bean的定义信息。
11.基于Groovy DSL的配置
这个稍微看一下,以后要用到再详细看。
12.通过编码方式动态添加Bean
(1)通过DefaultListableBeanFactory,可以扩展配置、循环枚举,实现Bean动态注入,除此之外还要实现BeanFactoryPostProcessor接口。
(2)扩展自定义标签,需要经过一下步骤:
1.采用XSD描述自定义标签的元素属性;
2.编写Bean定义的解析器;
3.注册自定义标签解析器;
4.绑定命名空间解析器。
13.不同配置方式比较
Bean不同配置方式的使用场景:
总结
这一章详细地介绍了Bean的配置,受益匪浅。