关于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对象 在RPC应用中,进行跨进程远程调用的时候,需要使用特定的序列化技术,需要对进行网络传输的对象进行序列化和反序列化. ...

  2. .NET Core 性能分析: xUnit.Performance 简介

    xunit-performance 是xUnit的一个扩展, 使用它可以对.NET Core项目进行性能测试. 官网:https://github.com/Microsoft/xunit-perfor ...

  3. 安恒杯 3月线上个人赛WriteUp

    #前言 这次做的还挺多的,只有个Web300没做出来,排名由上次60+进步到这次16名(最后三分钟掉了5名),感觉还是不错的.但是很明显,流量题有很大的运气成分.做完流量题之后还剩一个多小时,水了水M ...

  4. 如何在ASP.NET Core程序启动时运行异步任务(2)

    原文:Running async tasks on app startup in ASP.NET Core (Part 2) 作者:Andrew Lock 译者:Lamond Lu 在我的上一篇博客中 ...

  5. 使用Maven的assembly插件实现自定义打包

    一.背景 最近我们项目越来越多了,然后我就在想如何才能把基础服务的打包方式统一起来,并且可以实现按照我们的要求来生成,通过研究,我们通过使用maven的assembly插件完美的实现了该需求,爽爆了有 ...

  6. c#文件图片操作

    系统特殊目录路径 //取得特殊文件夹的绝对路径 //桌面 Environment.GetFolderPath(Environment.SpecialFolder.Desktop); //收藏夹 Env ...

  7. 从PRISM开始学WPF(二)Prism-更新至Prism7.1

    0x1 PRISM? PRISM项目地址:https://github.com/PrismLibrary/Prism 先看下简介: Prism is a framework for building ...

  8. Prism定制Region控件

    并不是所有控件都可以被用作Region了吗?我们将Gird块的代码变成这样: <Grid> <ContentControl prism:RegionManager.RegionNam ...

  9. SLAM+语音机器人DIY系列:(四)差分底盘设计——4.底盘ROS驱动开发

    摘要 运动底盘是移动机器人的重要组成部分,不像激光雷达.IMU.麦克风.音响.摄像头这些通用部件可以直接买到,很难买到通用的底盘.一方面是因为底盘的尺寸结构和参数是要与具体机器人匹配的:另一方面是因为 ...

  10. 简述ADO.NET的连接层

    前面曾提到过ADO.NET的连接层允许通过数据提供程序的连接.命令.数据读取器对象与数据库进行交互.当想连接数据库并且使用一个数据读取器对象来读取数据时.需要实现下面的几个步骤 * 创建.配置.打开连 ...