名词解释:
Bean: Bean就是由Spring容器初始化,装配及被管理的对象,实际上Bean就是对象。
BeanFactory: BeanFactory是访问Spring beans的一个容器。所有的Spring Beans的定义都会在这里被统一的处理。换句话说,BeanFactory interface是一个应用组件(Spring Bean)的集中注册器和配置器。从一般意义上来讲,BeanFactory是用来加载和管理Spring Bean definition的。但是同时BeanFactory对Spring Bean definition存于何处则不关心。
观察其定义:
public interface BeanFactory {
Object getBean(String name) throws BeansException;
Object getBean(String name, Class requiredType) throws BeansException;
boolean containsBean(String name);
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
Class getType(String name) throws NoSuchBeanDefinitionException;
String[] getAliases(String name) throws NoSuchBeanDefinitionException;
}
BeanFactory管理的两类对象:sington&prototype
Sington
Prototype
开场白:Spring FrameWork的核心是控制反转容器(IoC),而BeanFactory则是控制反转容器的核心接口。
那么,什么是控制反转呢:
首先。我们需要了解什么是对象依赖。
如果你想认识一个女孩,你会怎么做呢
假设有如下代码:
public class Boy {
void Find Girl (){
Girlkity= new Girl ();
}
}
是的,我们完全可以自己找,但是我们或许不能首先提出分手了,因为毕竟是自己主动的,或许这个比喻不很确切,但是肯定的一点是,如果你想把女友从kity更换成jess的话,你必须自己去说服kity分手,再去追求jess。这太麻烦了。(即如果Girl对象发生改变时,我们可能不得不去更改对象Boy的代码)
或许我们可以找朋友来帮我们介绍吧
public class Boy {
void Find Girl (){
Girlgirl = GirlFactory.createGirl ();
}
}
真是好方法,但是这样介绍总觉得有点不对劲,为什么要一个介绍人夹在我和女孩之间呢,介绍成功了我还得请客吃饭,真的不爽啊。所以找家里人帮我介绍吧,我们将找女孩的要求写在纸上,交给家里人,就i等着女孩上门吧,以后想换一个也不用自己出马了。
public class Boy {
void Find Girl (Girl girl){
girl.LoveMe()
}
对于第一种情况, Boy自己建立自己的Girl,很难共享,只能单独使用,并完全的生命周期。
对于第二种情况,我们不希望出现额外的非标准的中介,这样会加剧对象之间的耦合程度
对于第三种情况,可能有人要说void Find Girl (Girl girl)这一句中,如果Boy不知道Girl对象是不会通过编译的,这和第一种情况又有什么区别呢.有两点,我们注意到不同类型女孩的属性可能不同,但是她们的行为能力(方法)基本无异,则我们可以运用面向接口编成的方法来包容我们对象的一些差异,更为重要的一点,我们接收到的Girl对象是已经存在的对象,是初始化完毕的对象,我们不需要在Boy中对Girl对象的一些属性进行设置,这些工作完全从Boy对象中被剥离开来了,实现了对象间的松耦合.
下面来看Spring中一个典型的反转控制的实现:
定义Action接口:
public interface Action {
public String execute(String str);
}
Action接口的两个实现UpperAction、LowerAction
public class UpperAction implements Action {
private String message;
public String getMessage() {
return message;
}
public void setMessage(String string) {
message = string;
}
public String execute(String str) {
return (getMessage() + str).toUpperCase();
}
}
public class LowerAction implements Action {
private String message;
public String getMessage() {
return message;
}
public void setMessage(String string) {
message = string;
}
public String execute(String str) {
return (getMessage()+str).toLowerCase();
}
}
Spring配置文件(bean.xml)
<beans>
<description>Spring Quick Start</description>
<bean id="TheAction"
class="net.xiaxin.spring.qs.UpperAction">
<property name="message">
<value>HeLLo</value>
</property>
</bean>
</beans>
测试代码
public void testQuickStart() {
ApplicationContext ctx=new
FileSystemXmlApplicationContext("bean.xml");
Action action = (Action) ctx.getBean("TheAction");
System.out.println(action.execute("Rod Johnson"));
}
分析以上代码,我们可以看到,UpperAction、LowerAction实现了Action接口,Action方法分别返回对象中私有变量message和接受到的参数str相连接所构成的字符串的大写形式和小写形式。
注意bean.xml配置文件中的内容,bean id="TheAction"
class="net.xiaxin.spring.qs.UpperAction" 这一句定义了一个bean,并将这个bean和一个对象相关联,这个对象正是UpperAction。<property name="message"><value>HeLLo</value> 这一句让我们在创建这个对象实例的时候能够自动将其message参数赋值为“Hello”。
接着看测试代码,ApplicationContext ctx=new
FileSystemXmlApplicationContext("bean.xml");这条语句使用配置文件实例化容器;Action action = (Action) ctx.getBean("TheAction");容器根据配置文件生成了一个action实例;System.out.println(action.execute("Rod Johnson"));我们赋给action一个参数Rod Johnson并输出action返回的结果。
最后,我们得到输出Hello Rod Johnson。
由此我们可以看出,容器的工作就是在创建bean时注入那些依赖关系(根据配置文件)。相对于bean自己来控制其实例化,直接在构造器中指定其依赖关系,控制在根本上发生了倒转,这就是IoC名字的由来。
Spring的依赖注入机制,可以在运行期为组件配置所需资源,而无需在编写组件代码时就加以指定,从而在相当程度上降低了组件之间的耦合。