Spring -- 3.1
Spring的启动过程是怎样的?
spring的国际化和监听,先Let it go吧~~
Spring像一台构造精妙的仪器,我们通过配置文件向机器传达控制信息,机器就能按照设定的模式进行工作。如果把Spring看作一辆汽车,那么BeanFactory就是汽车的发动机,而ApplicationContext就是整辆汽车。
Spring中的AbstractApplicationContext是ApplicationContext的抽象实现,该类中的refresh()方法定义了容器在加载配置文件后的各项处理过程。这个过程就是Spring启动的时候所执行的各种操作,揭示了Spring的启动过程。
先上一张整体的图:
//1、初始化BeanFactory ConfigurableListableBeanFactory beanFactory = getBeanFactory();
根据配置文件实例化BeanFactory,getBeanFactory()具体有子类实现。在这一步里Spring把配置文件的信息装配到容器的Bean定义注册表(BeanDefinitionRegistry)里面,此时Bean还没有初始化。
//2、调用工厂后处理器 invokeBeanFactoryPostProcessor();
根据反射机制找出BeanDefinitionRegistry中所有BeanFactoryPostProcessor类型的Bean(应该是实现了某一个接口的类),并调用postProcessorBeanFactory()接口的方法。
//3、注册Bean后处理器 registryBeanPostProcessor()
注册Bean后处理器,根据反射机制从BeanDefinitionRegistry找出所有BeanPostProcessor类型的Bean(也是实现了某一接口的类),并将它们注册到容器Bean后处理器注册表中。
//4、初始化消息源 initMessageResource()
初始化容器的国际化信息资源。
//5、初始化应用上下文广播事件 initApplicationEventMulticaster();
初始化应用上下文广播事件。
//6、初始化其他特殊的Bean:由具体子类实现 onRefresh();
//7、注册事件监听器 registerListeners();
//8、初始化所有单实例的Bean,使用懒加载模式的除外。 finishBeanFactoryInitialization(beanFactory)
初始化Bean并把它们放到Spring的缓存中,就是一个Map中。
//9、完成刷新并发布容器刷新时间 finishRefresh()
看完这个过程,尼玛和不看是一样的,具体是做什么的?还是不知道啊,这些专业的术语尼玛太抽象了~~
我们看图:
- ResourceLoader从存储介质中(就是配置文件)加载Spring配置文件,并使用Resource表示这个资源(这个ResourceLoader在后面再介绍一下)。
- BeanDefinitionReader(这个是Spring中定义的一个类),读取配置文件,解析配置文件。配置文件中的每一个<bean>被解析成一个BeanDefinition对象,并保存到BeanDefinitionRegistry中(这个就是一个Map)。这一步并没有完全的解析。
- 容器扫描BeanDefinitionRegistry中的BeanDefinition,使用Java反射机制自动识别出Bean工厂后处理器(实现了BeanFactoryPostProcessor接口)的类,然后调用Bean工厂后处理器对BeanDefinitionRegistry中的BeanDefinition进行处理,主要完成两项工作:
- 对使用占位符的<Bean标签进行解析,得到最终的配置,这意味着对未完全解析的BeanDefinition进行处理并得到最终的BeanDefinition
- 对BeanDefinitionRegistry中的BeanDefinition进行扫描,通过反射机制找出所有的属性编辑器Bean(实现了java.beans.PropertyEditor接口),并自动注册到Spring容器的属性编辑器注册表中(PropertyEditorRegistry),注入很关键了一步。这个属性编辑器就是将外部设置的值转换为JVM内部的对应类型,就是一个类型转换器(配置文件中配置一个5,要转换成具体的int、Double等)。
- Spring容器从BeanDefinitionRegistry中取出加工后的BeanDefinition,并调用InstantiationStrategy进行Bean的实例化工作;
- 在实例Bean的时候,Spring容器使用BeanWrapper对Bean进行封装,BeanWrapper提供了很多Java反射机制操作Bean的方法,它结合BeanDefinition以及容器中的属性编辑器,完成Bean属性的设置工作。
- 利用容器中注册的Bean后处理器(实现BeanPostProcessor接口的Bean),对已经完成属性设置的Bean进行后续加工,直接装配出一个完整的Bean。
现在应该稍稍清楚一点了吧。先这样吧,具体的东西还需要一点一点的去研究源码,先把整个过程把握一下。
有关Spring的Resource、ResourceLoader
书上是这么说的:JDK提供的资源访问类(java.url.net 、File等),并不能很好的满足底层资源访问的需求。比如 确实从类路径或者Web容器的上下文中获取资源的操作类。因此,Spring设计了一个Resource接口,为应用提供更强的底层访问能力。这个接口的主要方法:
boolean exists()
boolean isOpen()
URL getURL() throws IOException
File getFile() throw IOException
InputStream getInputStream() throws IOException
具体就不解释了。Spring使用Resource装载配置文件、国际化属性文件资源等,用图了解一下它的实现类:
Spring提供了一套资源加载的接口,并提供了实现类。