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 ...
随机推荐
- Java集合框架详解(全)
一.Java集合框架概述 集合可以看作是一种容器,用来存储对象信息.所有集合类都位于java.util包下,但支持多线程的集合类位于java.util.concurrent包下. 数组与集合的区别如下 ...
- vscode创建net core控制台程序
vscode近来深受的开发人员的喜爱.在下的前端同事们也纷纷使用vscode.在下就想了我等后端程序员也可以用vscode写C#代码.毕竟是从宇宙第一IDE ----Visual Studio衍生的 ...
- 震惊!计算机连0.3+0.6都算不对?浅谈IEEE754浮点数算数标准
>>> 0.3+0.6 0.8999999999999999 >>> 1-0.9 0.09999999999999998 >>> 0.1+0.1+ ...
- Java笔试题库之选题题篇【1-70题】
1.下面中哪两个可以在A的子类中使用:( ) class A { protected int method1 (int a, int b) { return 0; } } A. public int ...
- js node.js 编写命令工具demo
1 创建文件夹cli-demo 2 执行npm init 3 创建cli.js 文件 内容如下: //js文件变成可执行文件 #!/usr/bin/env node console.log(&quo ...
- docker~aspnetcore2.0镜像缺少libgdiplus问题
回到目录 对于微软官方提供的镜像microsoft/aspnetcore2.0来说,它没有安装libgdiplus包,所以当你使用了draw去画图时,就会出现一些问题,我们一般会安装第三方的包包,ZK ...
- Unity资源打包学习笔记(二)、如何实现高效的unity AssetBundle热更新
转载请标明出处:http://www.cnblogs.com/zblade/ 0x01 目的 在实际的游戏开发中,对于游戏都需要进行打补丁的操作,毕竟,测试是有限的,而bug是无法预估的.那么在手游中 ...
- 接口自动化:HttpClient + TestNG + Java(一) - 接口测试概述+自动化环境搭建
1.1 接口测试简介 1.1.1 什么是接口测试 开始学习接口自动化测试之前,我们先要来了解什么是接口,以及什么是接口测试. 我们都知道,测试从级别上划分可以分为 组件测试 集成测试 系统测试 验收测 ...
- 微信小程序开发05-日历组件的实现
接上文:微信小程序开发04-打造自己的UI库 github地址:https://github.com/yexiaochai/wxdemo 我们这里继续实现我们的日历组件,这个日历组件稍微有点特殊,算是 ...
- kubectl自动补全
source <(kubectl completion bash) echo "source <(kubectl completion bash)" >> ...