深⼊理解Spring框架-启动Bean加载过程
1. spring web应⽤启动过程核⼼流程:
(1)web 容器启动时,⾸先加载l ⽂件,并逐⼀解析l⽂件内容配置,优先解析的是内容上下⽂加载配置:
org.t.ContextLoaderListener, 该配置主要⼯作是:基于contextClass以及servlet的上下⽂参数中context-param指定的spring配置⽂件去创建⼀个web 应⽤上下⽂—初始化root application context 以及通过指定应⽤上下⽂的配置⽂件进⾏初始化加载。
(2)调⽤ContextLoaderListener:: contextInitialized ⽅法对根应⽤上下⽂进⾏初始化. contextInitialized ⽅法中调⽤了⼀个ContextLoaderListener⽗类ContextLoader上下⽂加载器⽅法:initWebApplicationContext(ServletContext);
(3) ContextLoader::initWebApplicationContext(ServletContext) 的职责⼯作:创建⼀个可配置的web应⽤上下⽂(将上下⽂存储在本地实例变量中,以确保它在servletcontext关闭时可⽤),并设置其⽗上下⽂,然后调⽤
ContextLoader::configureAndRefreshWebApplicationContext;
(4) ContextLoader::configureAndRefreshWebApplicationContext() 主要⼯作:⾸先获取到spring上下⽂配置⽂件路径-configLocationParam=classpath:l(在l > listener >context-param 指定),设置⾃定义的上下⽂初始化器(ApplicationContextInitializer),并进⾏初始化;然后调⽤ConfigurableWebApplicationContext的核⼼⽅法:refresh();
2. 上下⽂刷新refresh⼯作流程如下
代码流程:{
prepareRefresh();
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
prepareBeanFactory(beanFactory);
postProcessBeanFactory(beanFactory);
invokeBeanFactoryPostProcessors(beanFactory);
registerBeanPostProcessors(beanFactory);
initMessageSource();
initMessageSource();
initApplicationEventMulticaster();
onRefresh();
registerListeners();
finishBeanFactoryInitialization(beanFactory);
finishRefresh();
}
step1:prepareRefresh 上下⽂刷新前准备⼯作:设置ConfigurableWebApplicationContext上下⽂实例对象wac的启动⽇期和活动标志、加载属性源配置以及判断必填项是否都完整。
step2: obtainFreshBeanFactory 通知⼦类刷新内部bean⼯⼚⼯作:创建BeanFactory,如果已有就销毁,没有就创建;核⼼⼯作就是解析XML 以及扫描注解 将扫描到的Bean配置属性封装到BeanDefinition 对象中,并对它beanName(key) ,
BeanDefinition(v) 保存到⼀个Map 中。
step3:prepareBeanFactory 对bean factory进⾏⼀些上下⽂标准化配置:设置factory的类加载器、bea
n 表达式解释器、资源编辑注册器、应⽤上下⽂⾃动注⼊后处理器、配置在⾃动装配(通过beans标签default-autowire属性来依赖注⼊)的时候的需要忽略的类(如ApplicationContextAwareProcessor、EnvironmentAware、ResourceLoaderAware、EmbeddedValueResolverAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware)、注册可以⾃动装配的 Bean(如BeanFactory)以及注册默认系统变量配置等。
[⾃动装配与@Autowired 的区别:⾃动装配指通过beans标签default-autowire属性来依赖注⼊的⽅式,
⽽不是指使⽤@Autowired注解进⾏的依赖注⼊。区别在于,使⽤default-autowire会⾃动给所有的类
都会从容器中查匹配的依赖并注⼊,⽽使⽤@Autowired注解只会给这些注解的对象从容器查依赖并注⼊]
step4: postProcessBeanFactory 修改BeanFactory的后处理器配置:在标准初始化之后修改应⽤程序上下⽂的内部bean⼯⼚初始化配置,允许注册特殊BeanPostProcessors->即ServletContextAwareProcessor 后处理器以及设置⾃动装配忽略接⼝类(ServletContextAware、ServletConfigAware)以及注册应⽤上下⽂的request/session 范围。 这⼀阶段所有bean定义都已加载,但没有bean将被实例化。
step5:invokeBeanFactoryPostProcessors ⼯作:通过显⽰顺序⽅式调⽤⼿动注册的BeanFactory后处理器,先实例化spring框架涉及到的后处理器,在调⽤。
(1)先执⾏ BeanDefinitionRegistryPostProcessor 的⽅法
(2)对配置/组件类中声明的嵌套@component类或configuration类者进⾏⾃动注册成bean定义,并对这些候选bean定义按照优先级进⾏排序。
(3)执⾏beanFactoryPostProcessors,对配置⽂件bean进⾏扫描实例化:如propertyConfigurer。
step6:registerBeanPostProcessors 注册拦截bean创建的bean处理器-实例化:
(1):通过BeanNamesForType(BeanPostProcessor.class, true, false);⽅法获取beanFactory⾥继承了BeanPostProcessor接⼝的name的集合;
(2):把后置器beans分为PriorityOrdered、Ordered、nonOrdered三⼤类,前两类是增加了排序条件的后置器;
(3):前两类后置器执⾏sortPostProcessors和registerBeanPostProcessors⽅法,也就是先执⾏排序⽅法,后执⾏注册⽅法。
(4):最后⼀步⽤到了上⾯提到的BeanPostProcessor和BeanFactoryPostProcessor的⼊参不同的AbstractApplicationContext,在addBeanPostProcessor⽅法⾥把BeanPostProcessor注册进了AbstractBeanFactory,这也就是为什么BeanFactoryPostProcessor执⾏了后置接⼝实现类,⽽BeanPostProcessor仅仅执⾏了注册和实例化,⽽没有执⾏的原因。
step7:initMessageSource 初始化消息源:MessageSource接⼝类⽤于⽀持信息的国际化和包含参数的信息的替换。ApplicationContext接⼝继承了MessageSource接⼝,应⽤可通过ApplicationContext来调⽤MessageSource接⼝⽅法以实现信息的国际化和替换信息中包含的参数。所有对MessageSource接⼝的实现都是在AbstractApplicationContext中实现。
step8: initApplicationEventMulticaster 初始化事件⼴播器:如果上下⽂中没有定义则使⽤默认⼴播器:SimpleApplicationEventMulticaster。
step9: onRefresh 初始化其他特定的bean,由具体⼦类实现。
step10:registerListeners 注册监听事件:在容器中将所有项⽬⾥⾯的ApplicationListener注册进来,⼤体过程如下:获取所有的
事件,并添加到事件派发器中 -> 监听事件进⾏派发⼴播。
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
...
getApplicationEventMulticaster().multicastEvent(earlyEvent)
step11: finishBeanFactoryInitialization 初始化所有剩下的单实例 Bean(没有配置赖加载的 lazy!=true)。⼤体过程如下:
-> 获取bean的定义信息
-> 判断bean 是否是抽象的、是单例的、⾮懒加载的
-> 是否为 FactoryBean ,是则调⽤ FactoryBean 的创建⽅法,否则执⾏ getBean() ⽅法
-> 调⽤ getBean() ⽅法
-> getBean⽅法内部再调⽤ doGetBean() ⽅法
step12:finishRefresh 完成BeanFactory的初始化创建⼯作:
// 初始化⽣命周期处理器组件
initLifecycleProcessor();
// ⾸先将刷新状态传播到⽣命周期组件中.
getLifecycleProcessor().onRefresh();
// 发布上下⽂已刷新完毕的事件.
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active:
LiveBeansView活动beans的查看适配器,构建当前bean的快照和来⾃本地{@code ApplicationContext}的依赖关系(带有本地{@code LiveBeansView } bean定义)或所有已注册的ApplicationContexts由{@value #MBEAN_DOMAIN_PROPERTY_NAME}环境属性驱动)
3. obtainFreshBeanFactory ⼯作流程
主要⼯作解析web项⽬配置(在l > listener >context-param 指定)的应⽤l⽂件的import、bean、resource、profile…等配置项的进⾏逐⼀解析。核⼼⼯作就是解析XML 或扫描注解,将其属性封装到BeanDefinition 对象中,并对它beanName(key) 、BeanDefinition(v) 保存到⼀个Map 中,为后⾯spring加载依赖注⼊提供了对应的元数据(bean 定义)。
在obtainFreshBeanFactory⽅法内部调⽤了refreshBeanFactory⽅法,此⽅法是执⾏应⽤上下⽂的基础bean⼯⼚的实际刷新,⾸先,若存在⼀个bean⼯⼚,进⾏关闭,其次创建⼀个新bean⼯⼚。
3.1 refreshBeanFactory ⼯作流程如下:
createBeanFactory()
->customizeBeanFactory() : 设置BeanFactory定制化信息:允许bean定义重载(allowBeanDefinitionOverriding)、允许循环引⽤(allowCircularReferences)
->loadBeanDefinitions(beanFactory) : 默认执⾏XmlWebApplicationContext的bean配置加载
-> loadBeanDefinitions(XmlBeanDefinitionReader render): 遍历所有配置⽂件
-> reader.loadBeanDefinitions(“classpath:l”)
2. List< Resource> resources = Resources(location):通过资源加载器加载资
resource和autowired注解的区别源-⽀持正则匹配查资源
->loadBeanDefinitions(Resource resource): 遍历所有资源resource
->loadBeanDefinitions(EncodedResource resource): Resource 转换成
EncodedResource
-> Resource().getInputStream() :读取⽂件流
-> doLoadBeanDefinitions(inputSource)
-> Document doc = loadDocument(inputSource) :根据xml schema解析成
xml⽂档对象
xml⽂档对象
-> registerBeanDefinitions(doc)
-> doRegisterBeanDefinitions(Element root): 核⼼逻辑 解析xml⽂档并注册
bean定义
3.2 doRegisterBeanDefinitions⽅法处理过程
(1) preProcessXml(root); // xml解析前处理⽅法:空处理,spring 框架提供⼦类扩展点
(2) parseBeanDefinitions(root, this.delegate); // 主要解析步骤,遍历解析root节点⼦节点
(3) postProcessXml(root) ;// xml解析后处理⽅法:空处理,spring 框架提供⼦类扩展点
parseBeanDefinitions 解析项分为两⼤类:⼀是spring默认配置项:import、alias、bean、beans 配置项,⼆是定制化的配置项:如component-scan、annotation-config、property-placeholder、mbean-export等。
(1). 解析< bean id="" classs="" />将element属性赋值到对应的AbstractBeanDefinition 定义的对象中
(2). 将AbstractBeanDefinition继续赋值给⼀个BeanDefinitionHolder(包含aliases、beanName、
beanDefinition)获取BeanDefinitionHolder对象的beanName和beanDefinition 将其注册到
BeanDefinitionRegistry 对象中(以beanName为key和beanDefinition为值value 保存到Map<String,
BeanDefinition> 中。)
(2). 遇到import配置项,依照上述步骤进⾏解析
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论