1. 为什么要有ApplicationContext
ApplicationContext
主要是为了将以下几个步骤(当然源spring
中可能有更多)整合起来,放到一个容器中,提供生命周期管理。
- 读
xml
文件,进行bean
的读取和beanDefinition
的读取 - 注册
postProcessor
- 注册
BeanFactoryPostProcessor
- invoke
BeanFactoryPostProcessor
如果不经过ApplicationContext,那么这一系列的过程大概是这样的,需要自己手动去注册路径,注册postprocessor等一系列的操作。
@Test
public void testBeanFactoryPostProcessorAndBeanPostProcessor() {
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinition("classpath:spring.xml");
BeanFactoryPostProcessor myBeanFactoryPostProcessor = (BeanFactoryPostProcessor) factory.getBean("myBeanFactoryPostProcessor");
myBeanFactoryPostProcessor.postProcessBeanFactory(factory);
factory.addBeanPostProcessor((BeanPostProcessor) factory.getBean("myBeanPostProcessor"));
UserService userService = factory.getBean("userService", UserService.class);
System.out.println(userService);
}
而有了ApplicationContext
后,这一系列的操作都被整合到ApplicationContext
的refresh
方法中了。
@Test
public void testXML() {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
applicationContext.registerShutdownHook();
UserService userService = applicationContext.getBean("userService", UserService.class);
System.out.println("测试结果:" + userService);
}
2. ApplicationContext
的结构
大概这个样子
继承:ApplicationContext
的一系列继承
组合:组合DefaultListableBeanFactory
,主要用于委托接口中的功能。
3. ApplicationContext
中需要实现的各个部分
整体就是refresh
中的九个步骤
public void refresh() throws BeansException {
// 1. 加载BeanDefinition
refreshBeanFactory();
// 2. 获取beanFactory
ConfigurableListableBeanFactory factory = getBeanFactory();
// 3. 添加ApplicationContextAwareProcessor
factory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// 4. 调用factoryPostProcessor
invokeBeanFactoryPostProcessor(factory);
// 5. 注册beanPostProcessor
registerBeanPostProcessor(factory);
// 6. 初始化事件
initApplicationEventMulticaster();
// 7. 注册listener
registerListener();
// 8. 这里会把所有的bean全部调用一次getBean方法
factory.preInstantiateSingletons();
// 9. finish
finishRefresh();
}
一些具体的实现
3.1 FactoryBean
**FactoryBean**
和**BeanFactory**
的区别
BeanFactory
是用来生成Bean
和管理Bean
的
而FactoryBean
也属于Bean
如果容器getBean
时发现是一个FactoryBean
,就会去调用FactoryBean
的getObject
方法。
这样做有什么用途呢?
一个实际的案例就是Mybatis
中,利用FactoryBean
为service
层的对象自动提供代理
在调用service
的createBean
时,去get
具体的ORM对象时,会调用他的getObject
方法。
3.2 ResourceLoader
和XmlBeanDefinitionReader
组合,从xml
中解析bean
对象
XmlBeanDefinitionReader
和ResourceLoader
组合,加载流并且获取流
ResourceLoader
的类结构
![6f9066b0befd2560ecb35b6deb60b47.jpg](https://img-blog.csdnimg.cn/img_convert/c19df4d6ac10e41d99170a265260f395.png#clientId=ubefb3246-44b9-4&from=drop&height=270&id=u7dfbe160&margin=[object Object]&name=6f9066b0befd2560ecb35b6deb60b47.jpg&originHeight=1080&originWidth=1440&originalType=binary&ratio=1&size=61846&status=done&style=none&taskId=uf750b49c-c8e9-43cd-a459-c3f1b9c184a&width=360)
3.3 Event and listener
这部分通过定义了一个ApplicationContextMulticaster
对象用来管理和通知listener
如果有event
发生
通过application.publishEvent
方式
那么就会通过ApplicationContextMulticaster
对象通知所有的listener
,listener
检查是不是自己的event
主要通过检查泛型类是否和event
一样
然后调用listener
的响应的方法。
3.4 Aware
Aware
的作用是给bean
提供了一个可以反向利用Spring framework
中组件的机会,他会在getBean
中的createBean
方法中判断bean
需要哪一个类型的aware
,然后调用相应的set
方法,将容器中的组件set
进去,大概像是这个样子(反射)
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationStartupAware) {
((ApplicationStartupAware) bean).setApplicationStartup(this.applicationContext.getApplicationStartup());
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
4. 总结
4.1 设计模式
- 经典的模板方法模式。(严格意义上来说不算是模板方法模式,只是把各个功能分层,不同的实现放到了不同的抽象类中。
- 委托模式。
ApplicationContext
也继承自BeanFactory
,但他的关于这部分的方法实现委托给了同样实现了该相关接口的DefaultListableBeanFactory
。但是ApplicationContext
实现ListableBeanFactory
二层子接口,但是DefaultListableBeanFactory
实现了三个二层子接口,为什么还能委托? 我感觉到就是这种模式的精妙之处,只把自己需要的部分委托出去。(有深意,注意理解)。 - 适配器模式。
DisposableBeanAdapter
(这个的作用是,将disposableBean
和destoryMethod
中的统一到一个adpater
中,然后容器统一去处理这个adpater
- 观察者模式。事件处理(使用经典的观察者模式)
multicaster
相当于subject
,listener
相当于订阅者,至于两者的绑定是在容器中的refresh
中进行的。(get
所有type
为applicationListener
的bean
,然后绑定)
4.2 接口的继承
慢慢体会到,接口这样分层的目的,可以起到控制权限的作用。