关于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. 如何在ASP.NET Core中使用JSON Patch

    原文: JSON Patch With ASP.NET Core 作者:.NET Core Tutorials 译文:如何在ASP.NET Core中使用JSON Patch 地址:https://w ...

  2. springboot~configserver里对重要信息进行RSA加密

    简介 参考:https://springcloud.cc/spring-cloud-dalston.html#_encryption_and_decryption_2 RSA非对称加密有着非常强大的安 ...

  3. IntelliJ IDEA~gradle环境配置

    Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化构建工具.它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,抛弃了基于XML的各种繁琐配置. Int ...

  4. OO Unit2多线程电梯总结博客

    OO Unit2多线程电梯总结博客 传说中的电梯居然就这样写完了-撒花

  5. Pi Hybrids问题

    Pi Hybrids问题 清华大学肖秀波梁湧老师翻译的Rardin教授的<运筹学>[1]已于今年年中出版,感谢机械工业出版社张有利老师的推荐和赠书,让我能看到如此完美的千页级宏篇译著.该书 ...

  6. Sql学习笔记(二)—— 条件查询

    上篇简单介绍了一下sql的一些基础增删改查语句,而针对多种多样的查询语句则未详细说明,这一篇继续记录一下关于各种条件查询的知识. 1.按列名进行查询 语句: select stuName , stuA ...

  7. 浅谈Quartz.Net 从无到有创建实例

    一.Quartz.Net介绍 Quartz.NET是一个开源的作业调度框架,非常适合在平时的工作中,定时轮询数据库同步,定时邮件通知,定时处理数据等. Quartz.NET允许开发人员根据时间间隔(或 ...

  8. OO第二次博客作业——电梯调度

    OO第二次博客作业——电梯调度 前言 最近三周,OO课程进入多线程学习阶段,主要通过三次电梯调度作业来学习.从单部电梯的傻瓜式调度到有性能要求的调度到多部电梯的调度,难度逐渐提升,对同学们的要求逐渐变 ...

  9. vue-router 页面布局

    在单页面应用程序(SPA)中,有些页面的布局结构是上下两块是固定,中间内容是变化的.这时在入口处固定上下部分就可以很好的解决这一问题.有少部分页面没有上下部分或不需要(如:用户注册.登陆页面),针对这 ...

  10. Gulp 前端优化

    使用方法: 下载 node.js , https://nodejs.org/en/,并安装 msi 一下命令都属于 dos 命令 node -v,npm -v,检验是否下载成功(出现版本号) 将 np ...