spring启动加载bean的过程
参考网站:https://blog.csdn.net/aini201/article/details/77097314当Web应用启动时,contextInitialized方法会执行载入根上下文(IOC容器):(1)spring的web项目启动的时候会,启动我们常用的监听类。<context-param><param-name>contex
参考网站:https://blog.csdn.net/aini201/article/details/77097314
当Web应用启动时,contextInitialized方法会执行载入根上下文(IOC容器):
(1)spring的web项目启动的时候会,启动我们常用的监听类。
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/classes/spring-context.xml</param-value>
</context-param>
<!-- Spring监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
spring容器启动原理,参考资料:https://blog.csdn.net/qq_31854907/article/details/86300901
(2)tomcat在加载web应用时候,会针对每个web.xml的监听器进行创建,看org.apache.catalina.core.StandardContext.listenerStart(),
public boolean listenerStart() {
if (log.isDebugEnabled())
log.debug("Configuring application event listeners");
String listeners[] = findApplicationListeners();
Object results[] = new Object[listeners.length];
boolean ok = true;
for (int i = 0; i < results.length; i++) {
if (getLogger().isDebugEnabled())
getLogger().debug(" Configuring event listener class '" + listeners[i] + "'");
try {
String listener = listeners[i];
results[i] = getInstanceManager().newInstance(listener);
} catch (Throwable t) {
t = ExceptionUtils.unwrapInvocationTargetException(t);
ExceptionUtils.handleThrowable(t);
getLogger().error(sm.getString("standardContext.applicationListener", listeners[i]), t);
ok = false;
}
}
if (!ok) {
getLogger().error(sm.getString("standardContext.applicationSkipped"));
return (false);
}
ArrayList<Object> eventListeners = new ArrayList<>();
ArrayList<Object> lifecycleListeners = new ArrayList<>();
for (int i = 0; i < results.length; i++) {
if ((results[i] instanceof ServletContextAttributeListener)
|| (results[i] instanceof ServletRequestAttributeListener)
|| (results[i] instanceof ServletRequestListener)
|| (results[i] instanceof HttpSessionIdListener)
|| (results[i] instanceof HttpSessionAttributeListener)) {
eventListeners.add(results[i]);
}
if ((results[i] instanceof ServletContextListener)
|| (results[i] instanceof HttpSessionListener)) {
lifecycleListeners.add(results[i]);
}
}
for (Object eventListener : getApplicationEventListeners()) {
eventListeners.add(eventListener);
}
setApplicationEventListeners(eventListeners.toArray());
for (Object lifecycleListener : getApplicationLifecycleListeners()) {
lifecycleListeners.add(lifecycleListener);
if (lifecycleListener instanceof ServletContextListener) {
noPluggabilityListeners.add(lifecycleListener);
}
}
setApplicationLifecycleListeners(lifecycleListeners.toArray());
if (getLogger().isDebugEnabled())
getLogger().debug("Sending application start events");
getServletContext();
context.setNewServletContextListenerAllowed(false);
Object instances[] = getApplicationLifecycleListeners();
if (instances == null || instances.length == 0) {
return ok;
}
ServletContextEvent event = new ServletContextEvent(getServletContext());
ServletContextEvent tldEvent = null;
if (noPluggabilityListeners.size() > 0) {
noPluggabilityServletContext = new NoPluggabilityServletContext(getServletContext());
tldEvent = new ServletContextEvent(noPluggabilityServletContext);
}
for (int i = 0; i < instances.length; i++) {
if (!(instances[i] instanceof ServletContextListener))
continue;
ServletContextListener listener = (ServletContextListener) instances[i];
try {
fireContainerEvent("beforeContextInitialized", listener);
if (noPluggabilityListeners.contains(listener)) {
listener.contextInitialized(tldEvent);
} else {
listener.contextInitialized(event);
}
fireContainerEvent("afterContextInitialized", listener);//注册事件
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
fireContainerEvent("afterContextInitialized", listener);
getLogger().error(sm.getString("standardContext.listenerStart", instances[i].getClass().getName()), t);
ok = false;
}
}
return (ok);
}
(3)具体的创建wepapplicationcontext的过程如下:
ContextLoaderListener.contextInitialized(ServletContextEvent event)
->ContextLoader.initWebApplicationContext(ServletContext servletContext)
启动spring容器
->ContextLoader.createWebApplicationContext(ServletContext sc) - - - - - 如果web.xml里没指定类型,默认是XmlWebAppalication()
->ContextLoader.configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) - - - - - - 配置和初始化 webApplicationContext的子类是ConfigrableWebApplicationContext
->ConfigurableWebApplicationContext.refresh() - - - - - ConfigurableWebApplicationContext是接口
->AbstractApplicationContext.refresh() - - - - - 启动 容器初始化
->AbstractApplicationContext.obtainFreshBeanFactory() - - - - - 创建BeanFactory(DefaultListableBeanFactory),以及工厂的初始化
->AbstractRefreshableApplicationContext.refreshBeanFactory() - - - - - 在这里创建了BeanFactory(DefaultListableBeanFactory)。然后开始loadBeanDefinitions,这是一个抽象方法,实际的载入是在XmlWebApplicationContext类里。
->XmlWebApplicationContext.loadBeanDefinitions(DefaultListableBeanFactory beanFactory) - - - -创建一个XmlBeanDefinitionReader,并启动bean定义信息的载入。
->XmlWebApplicationContext.loadBeanDefinitions(XmlBeanDefinitionReader reader) - - - 根据配置文件的locations,因为配置文件是xml的,所以使用的是XmlBeanDefinitionReader 。具体的载入过程是委托给BeanDefinitionReader完成的
->AbstractBeanDefinitionReader.loadBeanDefinitionReader - - - 这是一个抽象类,实际的载入是在XmlBeanDefinitionReader中实现的,抽象类是根据bean定义的xml配置文件的路径,生成resource。然后XmlBeanDefinitionReader根据resource开始具体载入BeanDefinition
->XmlBeanDefinitionReader.loadBeanDefinitionReader(Resource resource)
->XmlBeanDefinitionReader.loadBeanDefinitions(EncodedResource encodedResource) - - - 在读取器中,需要得到代表XML文件的resource,这个resource对象封装了对xml文件的IO操作,所以读取器可以在打开IO流后得到XML的文件对象。
->XmlBeanDefinitionReader.doLoadBeanDefinitions(InputSource inputSource, Resource resource) - - - -读取器在这里打开IO流后得到XML的文件Document对象(Document对象是通过XML解析器出来的,下面会再根据Spring Bean的规则再解析出BeanDefinition)。得到对象后就可以按照spring的Bean定义规则来对这个xml的文件档树进行解析了
->XmlBeanDefinitionReader.registerBeanDefinitions(Document doc, Resource resource) - - -这个方法启动对BeanDefinition的解析的详细过程,这个解析会使用到Spring的Bean的配置规则。具体的过程是有BeanDefinitionDocumentReader来完成的。
->BeanDefinitionDocumentReader.registerBeanDefinitions(Document doc, XmlReaderContext readerContext)
->DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(Document doc, XmlReaderContext readerContext) - - - - -DefaultBeanDefinitionDocumentReader 是BeanDefinitionDocumentReader的实现类,registerBeanDefinitions方法开始按照Spring Bean的规则解析Document对象
->DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(Element root) - - -解析过程是由BeanDefinitionParserDelegate对象来完成的。
->DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)
->DefaultBeanDefinitionDocumentReader.parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate)
->DefaultBeanDefinitionDocumentReader.processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate)
- - - - 解析的结果是由BeanDefinitionHolder来持有的,这个BeanDefinitionHolder对象封装了BeanDefinition,beanName,aliases等信息,用它来完成向IOC容器注册。
->BeanDefinitionParserDelegate.parseBeanDefinitionElement(Element ele)
->BeanDefinitionParserDelegate.parseBeanDefinitionElement(Element ele, BeanDefinition containingBean)
->BeanDefinitionParserDelegate.parseBeanDefinitionElement(
Element ele, String beanName, BeanDefinition containingBean) - - - 对xml配置文件中的配置的Bean进行详细解析,这里只是读取定义 的<bean>,并载入到BeanDefinition中去,这里不涉及对象的实例化过程,对象的实例化实际上是再依赖注入时完成的。
spring 加载重要过程
SpringApplication.run(Class<?>[] primarySources, String[] args) --- 开始启动spring应用
new SpringApplication() --- 实例化spring应用对象、以及一些相关信息的初始化
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); --- 通过SPI(spring.factories)机制加载初始化工具
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); --- 通过SPI(spring.factories)机制加载监听器
run() --- 开始spring应用启动过程
ConfigurableApplicationContext context = null; 定义spring容器的上下文环境,
context = createApplicationContext(); 初始化应用的上下文,并加载基础的注解解释器
BeanUtils.instantiateClass(Class<T> clazz) 进行上下文环境对象的实例化,及属性的初始化
prepareContext(context, environment, listeners, applicationArguments, printedBanner); 加载上下文所处的环境配置
refreshContext(context); 刷新加载上下文内容
((AbstractApplicationContext) applicationContext).refresh(); 更新spring容器上下文的底层信息
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); 创建并加载上下文context的bean工厂
invokeBeanFactoryPostProcessors(beanFactory); 调用bean工厂中的bean的解析器(xml形式的bean解析器,注解annotation形式的解析器),进行bean的加载
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); 加载bean
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); 通过制定的解析器加载bean
ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
processConfigBeanDefinitions(registry);
List<BeanDefinitionHolder> configCandidates = new ArrayList<>(); 包含着应用中所使用到的bean的信息(名称、指向的对象)
this.reader.loadBeanDefinitions(configClasses); 加载spring中通过xml或者annotation形式定义的bean,到context的factory中
更多推荐
所有评论(0)