关于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. 1. spring5源码 -- Spring整体脉络 IOC加载过程 Bean的生命周期

    可以学习到什么? 0. spring整体脉络 1. 描述BeanFactory 2. BeanFactory和ApplicationContext的区别 3. 简述SpringIoC的加载过程 4. ...

  2. node 中第三方模块的加载过程原理

    node 中第三方模块的加载过程原理 凡是第三方模块都必须通过 npm 来下载 使用的时候就可以通过require('包名') 的方式来进行加载才可以使用 不可能有任何一个第三方包和核心模块的名字是一 ...

  3. 你所不知道的SQL Server数据库启动过程(用户数据库加载过程的疑难杂症)

    前言 本篇主要是上一篇文章的补充篇,上一篇我们介绍了SQL Server服务启动过程所遇到的一些问题和解决方法,可点击查看,我们此篇主要介绍的是SQL Server启动过程中关于用户数据库加载的流程, ...

  4. (转)JVM类生命周期概述:加载时机与加载过程

    原文地址: http://blog.csdn.net/justloveyou_/article/details/72466105 JVM类加载机制主要包括两个问题:类加载的时机与步骤 和 类加载的方式 ...

  5. (4.21)SQL Server数据库启动过程(用户数据库加载过程的疑难杂症)

    转自:指尖流淌 http://www.cnblogs.com/zhijianliutang/p/4100103.html SQL Server数据库启动过程(用户数据库加载过程的疑难杂症) 前言 本篇 ...

  6. JVM-类加载过程(Java类的生命周期)

    什么是类加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构.类的 ...

  7. iOS之nib、xib及storyboard的区别及storyboard的加载过程

    先讲述下nib, nib是3.0版本以前的产物,在终端下我们可以看到,NIB其实是一个文件夹,里面有可执行的二进制文件: 区分xib和storyboard的区别? 不同点: 1> 无论nib也好 ...

  8. Spring Framework框架解析(1)- 从图书馆示例来看xml文件的加载过程

    引言 这个系列是我阅读Spring源码后的一个总结,会从Spring Framework框架的整体结构进行分析,不会先入为主的讲解IOC或者AOP的原理,如果读者有使用Spring的经验再好不过.鉴于 ...

  9. 动态符号链接的细节 与 linux程序的加载过程

    转: http://hi.baidu.com/clivestudio/item/4341015363058d3d32e0a952 值得玩味的一篇分析程序链接.装载.动态链接细节的好文档 导读: by ...

随机推荐

  1. Java集合框架详解(全)

    一.Java集合框架概述 集合可以看作是一种容器,用来存储对象信息.所有集合类都位于java.util包下,但支持多线程的集合类位于java.util.concurrent包下. 数组与集合的区别如下 ...

  2. vscode创建net core控制台程序

    vscode近来深受的开发人员的喜爱.在下的前端同事们也纷纷使用vscode.在下就想了我等后端程序员也可以用vscode写C#代码.毕竟是从宇宙第一IDE  ----Visual Studio衍生的 ...

  3. 震惊!计算机连0.3+0.6都算不对?浅谈IEEE754浮点数算数标准

    >>> 0.3+0.6 0.8999999999999999 >>> 1-0.9 0.09999999999999998 >>> 0.1+0.1+ ...

  4. Java笔试题库之选题题篇【1-70题】

    1.下面中哪两个可以在A的子类中使用:( ) class A { protected int method1 (int a, int b) { return 0; } } A. public int ...

  5. js node.js 编写命令工具demo

    1 创建文件夹cli-demo 2 执行npm init  3 创建cli.js 文件 内容如下: //js文件变成可执行文件 #!/usr/bin/env node console.log(&quo ...

  6. docker~aspnetcore2.0镜像缺少libgdiplus问题

    回到目录 对于微软官方提供的镜像microsoft/aspnetcore2.0来说,它没有安装libgdiplus包,所以当你使用了draw去画图时,就会出现一些问题,我们一般会安装第三方的包包,ZK ...

  7. Unity资源打包学习笔记(二)、如何实现高效的unity AssetBundle热更新

    转载请标明出处:http://www.cnblogs.com/zblade/ 0x01 目的 在实际的游戏开发中,对于游戏都需要进行打补丁的操作,毕竟,测试是有限的,而bug是无法预估的.那么在手游中 ...

  8. 接口自动化:HttpClient + TestNG + Java(一) - 接口测试概述+自动化环境搭建

    1.1 接口测试简介 1.1.1 什么是接口测试 开始学习接口自动化测试之前,我们先要来了解什么是接口,以及什么是接口测试. 我们都知道,测试从级别上划分可以分为 组件测试 集成测试 系统测试 验收测 ...

  9. 微信小程序开发05-日历组件的实现

    接上文:微信小程序开发04-打造自己的UI库 github地址:https://github.com/yexiaochai/wxdemo 我们这里继续实现我们的日历组件,这个日历组件稍微有点特殊,算是 ...

  10. kubectl自动补全

    source <(kubectl completion bash) echo "source <(kubectl completion bash)" >> ...