一直没有梳理过这些知识,导致没能有条理地,系统了解spring整体框架的工作原理。现到了有点迷茫的时候,趁着有时间从头梳理了一下spring的相关知识。了解Spring启动过程前先了解一下Spring的整体框架框架。
深入了解Spring前,先弄清楚几个问题:
[if !supportLists]1. [endif]Spring是什么?
[if !supportLists]2. [endif]使用Spring能给我们带来什么?
[if !supportLists]3. [endif]Spring的工作原理是什么?
Spring是一个全栈框架,提供了从表示层到业务层再到持久层的一套完整的解决方案。可以很方便地让应用集成第三方框架组件,快速集成第三方提供的功能。Spring属于低侵入式设计,可以降低各组件之间的耦合性,实现软件各层之间的解耦,加快应用的开发。
Spring框架的7个模块
组成Spring框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。每个模块的功能如下:
[if !supportLists]· [endif]核心容器:核心容器提供Spring框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory使用控制反转(IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。
[if !supportLists]· [endif]Spring Context:SpringContext是一个配置文件,向Spring框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。
[if !supportLists]· [endif]Spring AOP:通过配置管理特性,Spring AOP模块直接将面向方面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。
[if !supportLists]· [endif]Spring DAO:JDBC DAO抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。
[if !supportLists]· [endif]Spring ORM:Spring框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。
[if !supportLists]· [endif]Spring Web模块:Web上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。
[if !supportLists]· [endif]Spring MVC框架:MVC框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。
Spring的两大核心IOC和AOP。
以下介绍spring启动过程是基于springboot方式。
其入口就是SpringApplication.run(DemoApplication.class,args);
创建Spring上下文:Context = createApplicationContext();
其中webApplicationType由SpringApplication初始化时指定
this.webApplicationType = WebApplicationType.deduceFromClasspath();
从deduceFromClasspath方法可以看到,如果存在org.springframework.web.reactive.DispatcherHandler且不存在org.springframework.web.servlet.DispatcherServlet且不存在org.glassfish.jersey.servlet.ServletContianer时,WebApplicationType为REACTIVE,否则返回Servlet。此处采用的是默认配置,返回的是Servlet.
所以createApplicationContext初始化的为web.servlet.context.AnnotationConfigServletWebServerApplicationContext。
创建webApplicationContext后,刷新context前需完成一些准备工作prepareContext()方法。
Load(context,sources.toArray(new Object[0])方法根据注解,XML或componentScan路径加载bean并注册到BeanDefinitionMap中
刷新ApplicationContext前数据准备好了,接下来执行refreshContext(context)方法。
refreshContext(context)里调用refresh(context)方法
protected void refresh(ApplicationContext applicationContext) {
Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
((AbstractApplicationContext) applicationContext).refresh();
}
((AbstractApplicationContext) applicationContext).refresh();这一句话实际走的就是AbstractApplicationContext.refresh();
代码来到这里,就与传统的配置spring启动流程一样了。
其中有个关键的方法:obtainFreshBeanFactory(),看似个获取一个BeanFactory,其实这方法里做了很多事情,如:加载Bean并注册到spring容器。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory(); return getBeanFactory();
}
AbstractRefreshableApplicationContext.refreshBeanFactory()方法:
DefaultListableBeanFactory 是Spring整个bean加载的核心部分。
loadBeanDefinitions(beanFactory)方法,从方法名可以看出主要功能是解析配置文件中的bean定义并加载注册。
loadBeanDefinitions(beanFactory)解析XML的会走到AbstractXmlApplicationContext.loadBeanDefinitions(beanFactory)。最终会调用XmlBeanDefinitionReader.loadBeanDefinitions(EncodeResource encodeResource);
最后通过Document解析XML,并将XML定义的BEAN解析成BeanDefinition。最后通过BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());将BeanDefinition注册到BeanFactory中。
至些解析XML的obtainFreshBeanFactor()方法完成。
代码继续回到AbstractApplicationContext.refresh()方法中prepareBeanFactory(beanFactory);主要是对新实例化好的BeanFactory对象进行相关的参数设置。
invokeBeanFactoryPostProcessors(beanFactory)方法主要是判断BeanFactory中是否有指定类型的Bean,有则调用其相应的方法。
initApplicationEventMulticaster();方法主要是初始化一个applicationContext事件广播器。
onRefresh();模板方法,执行子类里的onRefresh方法。
registerListeners(); 主要是注册一些应用的监听器。
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);主要是实例化剩下所有的非懒加载的单例bean实体。
// Last step: publish corresponding event.
finishRefresh();
最后一步主要是清理一些缓存,触发context完成事件。
至此spring的启动基本完成。
总结:Spring的启动过程就是资源的加载和将注解BEAN或配置文件XML定义的BEAN转换成BeanDefinition并注册到BeanFactory,完成ApplicationContenct上下文创建的过程。
Spring的两大核心基础:BeanFactory,ApplicationContext
以上仅是本人的学习随笔笔记,由于能力有限可能存在错误的地方,欢迎指出。大家可以相互学习。