我的Pro Spring 学习笔记 之二 控制反转(IoC)和依赖注入(DI), Spring初步

我的Pro Spring 学习笔记 之二 控制反转(IoC)和依赖注入(DI), Spring初步

对应原书第四章

这些概念的讨论的资料在网上非常之多。所以本节基本上是罗列一些较为权威的连接,以及一些观点的摘要。
也会研究一些简单的例子来加深对概念的理解。
第一:观点
提到IoC和DI就不能不提Martin Fowler(http://martinfowler.com)。他的Inversion of Control Containers
 and the Dependency Injection pattern(http://martinfowler.com/articles/injection.html)一文是无论
 如何都必须要读过的。透明翻译的中文版的连接
 http://gigix.blogdriver.com/diary/gigix/inc/DependencyInjection.pdf。
CSDN上公布了Pro Spring书籍中文版的第四章http://book.csdn.net/bookfiles/48/100481401.shtml  。
当然,永远不要忘记Google。使用控制反转和依赖注入作为关键词可以搜索到数十万项条目。
第二:我的总结
1> 类似于Service Locator的依赖查找(非依赖注入)
这种方式使用之处是如此之多:JNDI, EJB, J2EE设计模式的Service Locator等。使用Spring的应用中也是以
这个方式根启动Spring 的BeanFactory/ApplicationContext的。但是。普遍的使用这种方式是不推荐的。
2>使用特定接口注入
因为其需实现特定的接口而有较强的侵入性,所以也不推荐。
3>构造器注入
4>Setter注入
关于上述两种注入方式的比较,在Martin的文章里讲了很多。Martin本身似乎更倾向于构造器注入。但事实上两
者的优缺点可以说是见仁见智。Spring的用户大多好像更倾向Setter注入。很明显,Pro Spring的作者也是倾向于
Setter注入的
Spring本身是既支持构建器注入,也支持Setter注入的。

Pro Spring中额外阐述了如下的Setter注入的优点
1>一个类在将他的依赖关系暴露给容器的同时,也希望自己保留一个缺省的依赖关系。(简单的说,就是在你不希
望容器注入依赖的时候,在配置中不申明依赖,在希望注入的时候申明依赖。而具体的类中,提供一个缺省的实现。)
2>允许商业接口中同时包含Setter以注入依赖。(这一段的翻译比较晦涩)
显然这一点是构造器注入无法达到的:但是也不能过度地使用这一特性。某种资源对于某一个特定的实现是必须的,
而对另一个特定的实现则并非必须。
Pro Spring书中提到的一些判断准则是:
a>被动的配置参数。这些参数值是辅助完成某一个商业逻辑,而非一个完整的商业逻辑
b>是一些消息片断而非其它组件
c>是一些简单的值和值的组合。
归根到底,决定是否在商业逻辑的结构中定义Setter的依据是其对所有的实现必须,还是只对特别的实现必须。
3>能够在运行起替换依赖的实现。

此外本章也讨论了一些其它的一些基本的特性, 如BeanFactory嵌套,自动装配,配置继承,别名等等。请参见以
下例程的讨论.
第三:例程。
1> HelloWorldXmlWithDI.java  使用xml方式配置。
看点1:使用了XmlBeanFactory
看点2:使用bean标记申明Bean, 使用ref标记配置依赖。
2> HelloWorldXmlWithConstructorDI.java 使用构造器注入
看点1:使用构造器注入值和对象
注意:ch2项目中的MessageRenderer必须要修改,注释掉setMessageProvider。(这也佐证了我们上面的学习:
商业接口中的Setter,一定要深思熟虑之后再加入。)
3>ConstructorConfusion.java
看点:通过指定type 避免构造器的混淆.
4>BeanFactory的嵌套
HierarchicalBeanFactoryUsage.java
对此小结一下:如果同名的话,子工厂内的定义覆盖父工厂的定义,除非使用parent来指明。子工厂来没有的,可以
用<ref bean="injectBeanParent"></ref>引用父工厂内的定义。而local总是在子工厂中寻找定义,如果找不到,则抛出
异常  org.springframework.beans.factory.BeanDefinitionStoreException
关于这个方面,可以看一下这个讨论:http://www.iteye.com/topic/15057。
5>注入集合
CollectionInjection.java
看点:注入集合的时候,map, list, set, Properties 都有不同的标签支持
6>Bean命名和Bean别名
BeanNaming.java
看点:Bean可以通过id, name, class等三种方式取得.name支持多个别名。
7>单例/非单例/对象池
NonSingleton.java
传统单例模式的短处: 将单一对象的维护和查找混合到了一起。无法实现面对接口编程。不能比较容易地替换实现。
而Spring管理单例则没有这方面的缺点。
缺省地,Spring创建的bean都是单例。关于这一点,可以参见讨论http://www.iteye.com/post/192557
(翻译有一处错误。原文是 Your application code must always have explicit knowledge of the Singleton
class in order to obtain the instance—completely removing the ability to code to interfaces.
译者翻译成了:你的应用程序代码必须知道单例类的确切信息才可以得到它的实例—完全地将这种能力转移到接口
的代码中。个人感觉上后半句应该译成:完全不符合依赖接口编程的良好习惯等。很明显这个误译和原文意思有点
相反了。code to
interfaces是惯用语,不是code of interfaces.这本书总体上翻译不错,但第四章翻译质量不高。再者全书使用术语不
够统一,也算是个缺点)
非单例:对于非单例对象,Spring不能管理其生命周期,也就是说,两个生命周期事件不会被触发。(详见下一章)
8>自动组装
autowring/Target.java
四种自动组装模式:byName, byType, consturctor, autodetect.
byType的组装方式, 如果有构造器的话,要求必须有一个缺省的无参构造器,否则报错。如果没有任何构造器的话,
不会报错。怀疑这是一个Spring的Bug,等网络恢复后查证。
autodetect则在byType和constructor方式之间做出选择。无任何构造器或者有一个缺省无参构造器的话,遵从byType。
否则遵从constructor。
9>申明依赖检查
关于依赖的两个配置属性。需要区分清楚。一个是depends-on。depends-on 反映的对象之间的依赖关系,即某个对象
必须在另一个对象之前完成初始化以提供必须的资源等.
另一个是dependency-check。这个是用来申明是否需要Spring来检查bean的每个属性在创建完成后都有对应的值。
simple: 只检查集合类和java内建类属性是否有值对应。
objects:只检查非内建类属性
all:检查全部
10>配置继承
依赖关系,单例模式,自动组装等不能被覆盖。
代码来源于书籍,略有改动

你可能感兴趣的:(spring,编程,bean,配置管理,IOC)