在这一节里我将介绍spring的容器,已经bean的装配
Spring的容器可以分为2类:
bean工厂(BeanFactory)和应用上下文(实现了ApplicationContext接口)
1. bean工厂(BeanFactory):
a. Bean工厂采用了工厂设计模式,但它又并非传统的工厂设计模式:传统的工厂设计模式只能得到同类型的Bean,而该工厂模式可以得到任意类型的Bean。
b. Bean工厂的工作:加载配置文件信息à实例化Beanà给Bean装配属性à分发Bean, Bean工厂还调用用户自定义的初始化和销毁方法,并管理Bean的生命周期。
c. Bean工厂有好几种实现,最长使用的是XmlBeanFactory,他根据xml配置文件来装载文件信息:
注意Spring3.0版本的装载方式:
BeanFactory factory=new XmlBeanFactory(new FileSystemResource(“XXX.xml”));
较老版本的Spring的XmlBeanFactory装载方式有些不同:
BeanFactory factory=new XmlBeanFactory(new FileInputStream(“XXX.xml”));
上面代码只是告诉Spring容器装载配置信息,但其实并未实例化Bean,只有当被需要的时候才进行实例化。
当需要一个Bean时,调用BeanFactory的getBean()方法传个名字给它就可得到一个指定的Bean。当调用getBean()方法时,才实例化配置信息。
2. 应用上下文(实现了ApplicationContext接口):
应用上下文相比Bean工厂提供了更多功能:
a. 载入文件资源的通用方法。
b. 文本信息解析工具。
c. 给Bean注册监听事件等。
以上功能将在后面陆续会有讲解…
在应用系统中基本选用ApplicationContext,它有多种实现:
a. ClassPathXmlApplicationContext,该实现会在类的全路劲下寻找配置文件载入信息。
b. FileSystemXmlApplicationContext,在文件里寻找指定配置文件信息载入。
c. XmlWebApplicationContext,从web系统中抄造xml文件载入上下文定义信息。
列子:
ApplicationContext appc=new ClassPathXmApplicationContext(“XXX.xml”);
MyBean bean=(MyBean)appc.getBean(“myBean”);
Bean工厂和应用上下文的还有一个非常重要的区别:
就是单例Bean的问题:Bean工厂不管是普通Bean还是单例Bean都是在有需要的时
候才实例化;而应用上下文则载入定义信息的时候首先把单例实例化,其他的Bean
则等有需要时才进行实例化。
注意:ApplicationContext不仅仅是容器的概念,它还提供了其他的服务 - 他当然他本身的核心功能是BeanFactory的功能。这个可以从它持有DefaultListableBeanFactory可以看到,它的IOC容器功能是通过持有的这个BeanFactory来实现的,另外再加上继承的DefaultResourceLoader,使得它具备了ResourceLoader的功能。
可以认为ApplicationContext对IOC容器(BeanFactory)作了进一步的拓展和封装,使得应用程序更好使用。
Bean的生命周期:
1. 容器寻找Bean的定义信息,然后实例化Bean。
2. 运用依赖注入,根据文件的定义信息配置Bean的属性。
3. 如果Name实现了BeanNameAware接口,则Spring(工厂)自动调用Bean的setBeanName(String id)方法传递Bean的ID。
4. 如果Bean实现了BeanFactoryAware接口,则工厂调用setBeanFactory()方法传入工厂本身。
5. 如果有BeanPostProcessor和Bean关联,那么他们的postProcessBeforeInitialization()方法将被调用。
6. 如果Bean指定了init-method方法,他将被调用。
7. 最后如果有BeanPostProcessor和Bean关联,那么他的postProcessAfterInitialization()方法将被调用。
这时候Bean可以被应用系统使用了,Bean将保存在BeanFactory中,直到它被删除
下面是Bean工厂中的生命周期图解
注意:应用上下文中的生命周期只有一点和Bean工厂不同,就是如果Bean实现了ApplicationContextAware接口,则它的setApplicationContext()方法将被调用,方法传一个ApplicationContextAware的实现类给他。
应用上下文中生命周期图解:
Spring提供了一个接口用于Bean的初始化:
InitializingBean接口:这个接口提供了一个afterPropertiesSet()这个方法将在所有的Bean属性设置后调用。
有2种方法把Bean从BeanFactory中删除:
1. 如果Bean指定实现了DisposableBean接口,则在Bean被删除的时候,它的destroy()方法将被调用。
2. 如果定制了销毁方法,则调用定制的方法。
Bean实现InitializingBean和BeanFactory接口后不需在文件中配置,Spring将自动识别,然后在规定条件下调用他们的方法。
Spring的装配方式有2种:手动装配和自动装配。由于手动装配(Set方式和构造方式注入)比较简单,我在这就不详细介绍,有不懂的朋友请自己查阅资料。
下面我将介绍下spring的自动装配:
先介绍4种装配类型:
1. byName --- spring会自动在容器中寻找和需要装配的属性名相同的Bean,如果没有找到则装配失败。
2. byTpye --- 在容器中自动寻找一个与需要装配的属性相同类型的Bean,如果没找到则装配失败,如果找到多个,则抛异常。
3. constructor --- 在容器中自动寻找和构造一致的Bean,如果构造不确定或有多个Bean一直导致无法确定,则抛异常。
4. autodetect --- 先尝试用constructor来自动装配,然后使用byType来自动装配。
可以混合使用手动和自动装配,规制如JAVA里的就进原则类似
还可在spring的根元素<beans default-autowire=”byName”>指定
提醒:在使用自动装配的时候要特别小心,一不小心就可能产生意想不到的异常。