Spring中的BeanFactory和ApplicationContext
BeanFactory和ApplicationContext
可以将IoC容器的初始化流程分为:
- 容器启动阶段
- Bean实例化阶段
容器启动化阶段:就是加载配置信息,使用 DefinitionReader 读取配置文件,然后将bean信息保存到BeanDefinition 中,一个bean对应一个BeanDefinition,并注册到BeanDefinitionRegistry中,总之一句话,就是读取配置信息,然后完成初始的准备工作
Bean实例化阶段:通过使用getBean()方法会触发该阶段的活动,首先检查请求的对象是否初始化,并为其注入依赖。如果对象实现了某些接口,会根据接口回调来装配,装配完成后,再将bean返回给调用者,一句话就是,生产具体的bean
BeanFactory启动只有第1个阶段,只有当对象调用到getBean()的时候,才会触发第二个阶段,因为BeanFactory默认使用的是懒加载模式
ApplicationContext启动后,会直接进行Bean实例化.
再来谈一下 BeanFactoryPostProcessor 和 BeanPostProcessor
BeanFactoryPostProcessor 作用于容器启动化阶段后期,作用的对象是 BeanDefinition 对象,
BeanPostProcessor 作用于Bean实例化阶段前期和后期,作用的对象是Bean,常用的两个方法:postProcessBeforeInitialization()、postProcessAfterInitialzation(),,常见的就像ApplicationContext对应的Aware接口,就是通过BeanPostProcesstor实现,Spring中的AOP很多就是使用BeanPostProcessor来为对象生成对应的代理对象,还有@Autowired,也是由BeanPostProcessor实现的,具体的实现类是AutowiredAnnotationBeanPostProcessor,有兴趣的可以看看源码
Bean的实例化和scope
IoC容器需要根据Bean对应的 BeanDefinition 信息来进行实例化,Spring中使用的是CGlib实现的动态生成,将 BeanDefinition 实例化后返回的是一个 BeanWrapper ,BeanWrapper只在Spring内部使用,使用BeanWrapper对bean进行操作比反射对bean操作要简单很多
常见的scope有:singleton,prototype,request,session,global session
singleton:整个IoC容器内只有一个实例,可以说与IoC容器的存活时间一样长
prototype:每次请求使用的时候,都会创建一个实例,IoC只负责创建实例,然后将实例返回给调用者,实例的生命周期由调用者负责
request:为每个HTTP请求创建一个RequestProcessor对象,请求结束后,该实例的生命周期就结束
session:为每个独立的session创建一个UserPreferences对象,相对来说,比request的bean的存活时间稍长一点
global session:用的少
ApplicationContext相比于BeanFactory增强的地方
- 统一资源加载策略:
Spring将资源划分为:ByteArrayResource(字节类型资源),ClassPathResource(从ClassPath加载的资源),FileSystemResource(对File文件的封装),UrlResource(对URL的封装),InputStreamResource(用的少,常被字节资源替代)
Spring提供了 ResourceLoader 来加载上述资源,常用的类有:DefaultResourceLoader,FileSystemResourceLoader,ResourcePatternResolver(批量查找)
重点来了,ApplicationContext继承接口中,有 ResourcePatternResolver,所以ApplicationContext 也可以看作是 ResourceLoader,支持统一资源加载 - 国际化信息支持(个人用的比较少,就不写东西误导大家了)
- 容器内部事件发布
有过开发经验的应该都知道,订阅-发布模式,JavaSE提供了一个EventObject(消息),EventListener(订阅者)来提供支持
ApplicationContext对其进行了改进,提供了ApplicationEvent,ApplicationContextListener来提供支持,提供的默认消息有,
ContextClosedEvent:容器即将关闭时发出
ContextRefreshedEvent:容器初始化或刷新的时候发出
RequestHandledEvent:Web请求处理后发布的事件
ApplicationContext继承了ApplicationEventPublisher,可以发布消息,ApplicationContext并没有亲自实现,而是将其委托给了ApplicationEventMulticaster
自定义消息发布:
step1:自定义一个消息类,继承自ApplicationEvent
step2:自定义一个定于这,继承自ApplicationListener
step3:自定义一个publisher,实现接口ApplicationEventPublisherAware
总结:只需要定义好消息处理逻辑,然后交给ApplicationContext,就会自动发布消息了
总结
BeanFactory和ApplicationContext都是Spring提供的IoC容器,ApplicationContext常用在Web环境下,对BeanFactory进行了一些增强,ApplciationContext增强的部分,是因为ApplicationContext额外继承的那部分接口,所以,只需要知道,这些接口的作用,基本上也就能分辨BeanFactory和ApplicationContext的区别的,总的来说,IoC容器基于启动阶段和Bean实例化阶段这两个阶段,并且提供BeanFactoryProcessor和BeanProcessor来对这两个阶段进行增强,所以,在开发过程中,绝大部分工作,都是围绕这两个阶段!