springIOC原理加载过程
关于spring ,我以前学过很多次,也看过很多的书.以及博客,但是总是不得要领,这次我再学习一遍,在这里做点记录,如果不对的地方还请大家指正
Ioc: inverse of controller 控制反转 . 对象的创建权利由程序反转给spring
什么是IOC容器呢?
所谓的IOC容器是指的spring bean 工厂里面MAP存储结构(存储了bean的实例)
spring框架中的工厂有哪些?
beanFactory 是spring早期创建bean对象工厂接口
applicationContext()接口实现了beanFactory接口
实现applicationContext接口的工厂,可以获取到容器中具体bean对象
实现了beanFactory接口的工厂也可以获取到bean对象
l ApplicationContext和BeanFactory的区别?
beanFactory采取的延迟加载,第一次getBean时才会初始化Bean
applicationContext是加载完applicationContext.xml 就创建了具体的bean实例(只对BeanDefition中描述是单例的bean,才进行恶汉模式创建)

这里我们看到顶层都是继承与beanfactory 我们常用的就是applicationContext
applicationContext接口常用实现类
- classpathXmlApplicationContext : 它是从类的跟路劲下加载配置文件,推荐使用这种
- FileSystemXmlApplicationContext: 它是从磁盘上加载配置文件,配置文件可以在磁盘的任意位置
AnnotationConfigApplicationContext : 当我们使用注解配置容器对象时,需要使用此类来创建 spring 容器。它用来读取注解。
IOC容器的创建方式
java创建IOC容器
ApplicationContext context = new ClassPathXmlApplicationContext(xml路径);
web 创建IOC 容器:(重点要知道)
- web服务器(tomcat)启动会加载web.xml(启动ContextLoaderListener监听器):
public class ContextLoaderListener extends ContextLoader implements ServletContextListener { public ContextLoaderListener(WebApplicationContext context) {
super(context);
} /**
serveltContext域对象创建的时候调用这个方法
* Initialize the root web application context.
*/
@Override
public void contextInitialized(ServletContextEvent event) {
//初始化web环境中的spring容器
initWebApplicationContext(event.getServletContext());
} /**
* Close the root web application context.
*/
@Override
public void contextDestroyed(ServletContextEvent event) {
closeWebApplicationContext(event.getServletContext());
ContextCleanupListener.cleanupAttributes(event.getServletContext());
} }
当我们点击initWebApplicationContext方法中的时候会发现以下源码
这个方法在contextLoader之中 也就是Contextloader创建spring容器并初始化spring bean实例
try {
// Store context in local instance variable, to guarantee that
// it is available on ServletContext shutdown.
if (this.context == null) {
//这一步就是创建spring容器
this.context = createWebApplicationContext(servletContext);
}
if (this.context instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
if (!cwac.isActive()) {
// The context has not yet been refreshed -> provide services such as
// setting the parent context, setting the application context id, etc
if (cwac.getParent() == null) {
// The context instance was injected without an explicit parent ->
// determine parent for root web application context, if any.
ApplicationContext parent = loadParentContext(servletContext);
cwac.setParent(parent);
}
//spring 容器初始化单例bean的实例
configureAndRefreshWebApplicationContext(cwac, servletContext);
}
}
configureAndRefreshWebApplicationContext 方法中调用最终初始化Bean的refresh方法
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
// The application context id is still set to its original default value
// -> assign a more useful id based on available information
String idParam = sc.getInitParameter(CONTEXT_ID_PARAM);
if (idParam != null) {
wac.setId(idParam);
}
else {
// Generate default id...
wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
ObjectUtils.getDisplayString(sc.getContextPath()));
}
}
wac.setServletContext(sc);
String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);
if (configLocationParam != null) {
wac.setConfigLocation(configLocationParam);
}
// The wac environment's #initPropertySources will be called in any case when the context
// is refreshed; do it eagerly here to ensure servlet property sources are in place for
// use in any post-processing or initialization that occurs below prior to #refresh
ConfigurableEnvironment env = wac.getEnvironment();
if (env instanceof ConfigurableWebEnvironment) {
((ConfigurableWebEnvironment) env).initPropertySources(sc, null);
}
customizeContext(sc, wac);
//不管是web还是java环境都是会调用这个方法实例化bean
wac.refresh();
}

如果web.xml中没有contextClass的元素,那么spring会找到自己的contextLoad.properties文件来加载
# Default WebApplicationContext implementation class for ContextLoader.
# Used as fallback when no explicit context implementation has been specified as context-param.
# Not meant to be customized by application developers. org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext
IOC容器如何加载bean对象呢?
跟着上面的refresh()方法我们来到他的源码看看
源码来自AbstractApplicationContext
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
//1. 创建真正的bean容器 ConfiurabaleBeanFactroy
//2.加载beandefiniton(描述要初始化的Bean的信息)
//3.将beandefiniton注册到BeanDefitionRegistry
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
//执行实现了BeanFactoryPostProcessor接口的Bean
//比如PropertyPlaceHolderConfigurer(context:property-placeholer)就是此处被调用的,替换掉BeanDefition中的占位符(${})中的内容
// Invoke factory processors registered as beans in the context.
//针对beandifition实例进行操作
invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation.
//主要针对bean实例进行操作的的,
//比如容器自动装载了一个AutowiredAnnotationBeanPostProcessor后置处理器(实现@Autowired注解功能)
registerBeanPostProcessors(beanFactory); // Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses.
onRefresh(); // Check for listener beans and register them.
registerListeners(); // Instantiate all remaining (non-lazy-init) singletons.
//初始化非懒加载方式的单例bean实例 自定的的java类 compent 之类的
这里的单例可以用过 scope作用域来进行自定义
finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event.
finishRefresh();
} catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
} // Destroy already created singletons to avoid dangling resources.
destroyBeans(); // Reset 'active' flag.
cancelRefresh(ex); // Propagate exception to caller.
throw ex;
} finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}

总结:
IOC 的原理有几点
什么是IOC?
什么是spring容器(IOC容器)?
如何创建spring容器?(java方式创建和webspring容器的创建方式)
spring容器如何初始化(就是bean实例 初始化的过程)?
DI介绍.
什么是DI 依赖注入
什么时候进行依赖注入?
在beandefinition 实例化bean的时候,还未初始化属性 这个时候就调用DI 通过set 或者 构造方式的注入
@Autowired注解,它是如何生效的?就是在beanpostProcessor对bean处理的时候调用AutowiredBeanPostProcessor类
springIOC原理加载过程的更多相关文章
- 1. spring5源码 -- Spring整体脉络 IOC加载过程 Bean的生命周期
可以学习到什么? 0. spring整体脉络 1. 描述BeanFactory 2. BeanFactory和ApplicationContext的区别 3. 简述SpringIoC的加载过程 4. ...
- node 中第三方模块的加载过程原理
node 中第三方模块的加载过程原理 凡是第三方模块都必须通过 npm 来下载 使用的时候就可以通过require('包名') 的方式来进行加载才可以使用 不可能有任何一个第三方包和核心模块的名字是一 ...
- 你所不知道的SQL Server数据库启动过程(用户数据库加载过程的疑难杂症)
前言 本篇主要是上一篇文章的补充篇,上一篇我们介绍了SQL Server服务启动过程所遇到的一些问题和解决方法,可点击查看,我们此篇主要介绍的是SQL Server启动过程中关于用户数据库加载的流程, ...
- (转)JVM类生命周期概述:加载时机与加载过程
原文地址: http://blog.csdn.net/justloveyou_/article/details/72466105 JVM类加载机制主要包括两个问题:类加载的时机与步骤 和 类加载的方式 ...
- (4.21)SQL Server数据库启动过程(用户数据库加载过程的疑难杂症)
转自:指尖流淌 http://www.cnblogs.com/zhijianliutang/p/4100103.html SQL Server数据库启动过程(用户数据库加载过程的疑难杂症) 前言 本篇 ...
- JVM-类加载过程(Java类的生命周期)
什么是类加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构.类的 ...
- iOS之nib、xib及storyboard的区别及storyboard的加载过程
先讲述下nib, nib是3.0版本以前的产物,在终端下我们可以看到,NIB其实是一个文件夹,里面有可执行的二进制文件: 区分xib和storyboard的区别? 不同点: 1> 无论nib也好 ...
- Spring Framework框架解析(1)- 从图书馆示例来看xml文件的加载过程
引言 这个系列是我阅读Spring源码后的一个总结,会从Spring Framework框架的整体结构进行分析,不会先入为主的讲解IOC或者AOP的原理,如果读者有使用Spring的经验再好不过.鉴于 ...
- 动态符号链接的细节 与 linux程序的加载过程
转: http://hi.baidu.com/clivestudio/item/4341015363058d3d32e0a952 值得玩味的一篇分析程序链接.装载.动态链接细节的好文档 导读: by ...
随机推荐
- SQL 高级查询(层次化查询,递归)
SQL 高级查询 前面我们写了一下 SQL 的极简入门,今天来说点高级查询.没看到的朋友可以点击下面链接查看. 1 小时 SQL 极速入门(一) 1 小时 SQL 极速入门(二) 1 小时 SQL 极 ...
- git的学习笔记(二):git远程操作
1.创建ssh key ssh-keygen -t rsa -C "your_email@example.com" 执行命令后会在用户的家目录生成.ssh的隐藏文件夹,文件夹里有公 ...
- mysql id从n 开始
mysql 全部删除数据后设置 id从1开始: truncate table table_name mysql 删除部分数据后设置 id从n开始 ALTER TABLE user auto_incr ...
- 机器学习之十一问支持向量机(SVM)
推导了支持向量机的数学公式后,还需要对比和总结才能更深入地理解这个模型,所以整理了十一个关于支持向量机的问题. 第一问:支持向量机和感知机(Perceptron)的联系? 1.相同点: 都是一种属于监 ...
- springboot~configserver里对重要信息进行RSA加密
简介 参考:https://springcloud.cc/spring-cloud-dalston.html#_encryption_and_decryption_2 RSA非对称加密有着非常强大的安 ...
- 为什么有那么多人愿意喝"鸡汤"?
什么是心灵鸡汤 心灵鸡汤,就是“充满知识与感情的话语”,柔软.温暖,充满正能量.心灵鸡汤是一种安慰剂,可以怡情,作阅读快餐:亦可移情,挫折.抑郁时,疗效直逼“打鸡血”.这也是“心灵鸡汤”风靡不衰的原因 ...
- C# NuGet包管理命令
NuGet Package Manager Console 内置于 Visual Studio 在 Windows 2012 和更高版本. (不包含在 Visual Studio 用于 Mac 或 V ...
- day09 css
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- Eclipse代码快捷键
今天终于找到了代码注释快捷键:ctrl+shift+/取消注释快捷键:ctrl+shift+\ Java文件:注释和取消注释的快捷键都是:CTRL + / 或 Shift+Ctrl+C JS文件:注释 ...
- Spring+MyBatis整合过程
步骤: 1.引入Spring+MyBatis开发包 >spring(ioc aop dao)开发包 >mybatis开发包,dbcp,驱动包 >mybatis-spring.jar整 ...