Spring容器并不是只有一个,Spring自带了多个容器实现,可以归为两种不同的类型,bean工厂(由org.springframework.beans.factory.BeanFactory接口定义)是最简单的容器,提供基本的DI支持,另一种是是应用上下文(由org.springframework.context.ApplicationContext接口定义),基于BeanFactory构造,可提供应用框架级别的服务,其中使用BeanFactory时,每次获取对象时才会创建对象,例如getBean(字符串名称)才会加载,ApplicationContext的各种实现类在加载这个xml文件时会创建该xml配置中的所有bean对象,默认单例singleton
Spring自带了多种类型的应用上下文,如AnnotationConfigApplicationContext、AnnotationConfigWebApplicationContext、ClassPathXmlApplicationContext、FileSystemXmlApplicationContext、XmlWebApplicationContext
FileSystemXmlApplicationContext在指定的文件系统路径下查找knight.xml文件,ClassPathXmlApplicationContext是在所有的类路径(包含JAR文件)下查找knight.xml文件
bean的生命周期:
实例化->填充属性->调用BeanNameAware的setBeanName()方法->调用BeanFactoryAware的setBeanFactory()方法->调用ApplicationContextAware的setApplicationContext()方法->调用BeanPostProcessor的初始化方法postProcessBeforeInitialization->调用InitializationBean的afterPropertiesSet()方法(可以增加一些额外的逻辑)->调用自定义的初始化方法->调用BeanPostProcessor的初始化后方法->bean可以使用了->容器关闭->调用DisposableBean的destroy()方法->调用自定义的销毁方法
1.Spring对bean进行初始化,如果是BeanFactory容器,客户请求一个尚未初始化的bean时,容器调用createBean进行实例化,如果是ApplicationContext容器,容器启动结束后,实例化所有bean,容器通过获取BeanDefinition对象中的信息进行实例化,并未依赖注入
2.Spring将值和bean的引用注入到bean对应的属性中,实例化对象被包装在BeanWrapper对象中,BeanWrapper提供了设置对象属性的接口,从而避免了使用反射机制设置属性
3.如果bean实现了BeanNameAware接口,Spring将bean的ID传递给setBeanName()方法
4.如果bean实现了BeanFactoryAware接口,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入
5.如果bean实现了ApplicationContextAware接口,Spring将调用setApplicationContext()方法,将bean所在的应用上下文的引用传入进来
6.如果bean实现了BeanPostProcessor接口,Spring将调用它的postProcessBeforeInitialization()方法,又称前置处理,会把bean对象传入
7.如果bean实现了InitializationBean接口,Spring将调用它们的afterPropertiesSet()方法,该方法不会把bean对象传入,只能增加一些额外的逻辑,例如使用init-method声明了初始化方法,该方法也会被调用
8.如果bean实现了BeanPostProcessor接口,Spring将调用它的postProcessAfterInitialization()方法,又称后置处理,会把bean对象传入
9.bean可以使用
10.如果bean实现了DisposableBean接口,Spring将调用它的destroy()接口方法,如果bean使用了destroy-method声明了销毁方法,该方法也会被调用