IOC原理之IoC容器的初始化过程

IOC容器初始化流程 了解过spring的都知道,spring是通过一个IOC容器管理应用中的bean对象的。本文讨论springboot应用在初始化IOC容器时的主要操作都有哪些。中提到refreshContext(context)实际会调用到AbstractApplicationContext的refres()方法。准备beanFactory,为其设置一些属性,如类加载器等。标记状态,校验必填属性,重置监听器状态等。提供先进的推理,复杂的指令,更多的创造力。为刷新上下文做一些准备工作,修改上下文的。 阅读详情
AI摘要

本文详细介绍了IoC容器初始化过程,包括Resource定位、BeanDefinition载入及注册等关键步骤,并以ClassPathXmlApplicationContext为例,深入分析了refresh()方法的具体实现。

IoC容器的初始化过程包括Resource定位、BeanDefinition的载入以及向IoC容器注册这些BeanDefinition三个阶段。

IoC容器的初始化过程概要

IoC容器的初始化包括三个过程:

  • 第一个过程是 Resource定位 过程。这个Resource定位指的是BeanDefinition的资源定位,它由ResourceLoader通过统一的Resource接口来完成,这个Resource对各种形式的BeanDefinition的使用都提供了统一接口。比如.在文件系统中的Bean定义信息可以使用FileSystemResource来进行抽象。在类路径中的Bean定义信息可以使用ClassPathResource来进行抽象等等。这个定位过程类似于容器寻找数据的过程,就像用水捅装水先要把水找到一样。

  • 第二个过程是 BeanDefinition的载入 。这个载入过程是把用户定义好的Bean表示成IoC容器内部的数据结构,而这个容器内部的数据结构就是BeanDefinition。下面介绍这个数据结构的详细定义。具体来说,这个BeanDefinition实际上就是POJO对象在IoC容器中的抽象。通过这个BeanDefinition定义的数据结构,使IoC容器能够方便地对Polo对象也就是Bean进行管理。

  • 第三个过程是 向IoC容器注册这些Bean Definition 的过程。这个过程是通过调用BeanDefinitionRegistry接口的实现来完成的。这个注册过程把载人过程中解析得到的BeanDeftnition向IoC容器进行注册。在IoC容器内部将BeanDefinition注人到一个HashMap中去,IoC容器就是通过这个HashMap来持有这些BeanDefinition数据的。

几个常用的ApplicationContext

1. FileSystemXmlApplicationContext

FileSystemXmlApplicationContext的继承体系:

由继承关系可知,FileSystemXmlApplicationContext通过继承AbstractApplicationContext具备了DefaultResourceLoader读取Resource定义的BeanDefinition的能力。因为AbstractApplicationContext的基类是DefaultResourceLoader。

看看其完整继承体系:

2. ClassPathXmlApplicationContext

ClassPathXmlApplicationContext的继承体系:

由继承关系可知,ClassPathXmlApplicationContext通过继承AbstractApplicationContext具备了DefaultResourceLoader读取Resource定义的BeanDefinition的能力。因为AbstractApplicationContext的基类是DefaultResourceLoader。和上面的FileSystemXmlApplicationContext如出一辙。

看看其完整继承体系:

3. AnnotationConfigApplicationContext

AnnotationConfigApplicationContext的继承体系:

可以看到,AnnotationConfigApplicationContext,也是通过DefaultResourceLoader读取Resource。

看看其完整继承体系:

详细分析IoC初始化过程

以常用的ClassPathXmlApplicationContext为例:

1、 新建resources/META-INF/spring/context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user" class="com.source.IoC.domain.User">
        <property name="name" value="张三"/>
    </bean>

</beans>

2、 新建User

public class User {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

3、


  public static void main(String args[]) {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext();

        applicationContext.setConfigLocation("classpath:/META-INF/spring/context.xml");
        applicationContext.refresh();

        User user = applicationContext.getBean("user", User.class);
        System.out.printf("user.getName() = %s \n", user.getName());
    }

运行main方法,整个运行过程如下:

所以这里主要要来看一看AbstractApplicationContext中的refresh() 这个函数:

 public void refresh() throws BeansException, IllegalStateException {
        Object var1 = this.startupShutdownMonitor;
        synchronized(this.startupShutdownMonitor) {
            this.prepareRefresh();
            //这里是在子类中启动refreshBeanFactory()定位并载入
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            //prepare the bean factory for use in this context
            this.prepareBeanFactory(beanFactory);

            try {
                //设置BeanFactory的后置处理
                this.postProcessBeanFactory(beanFactory);
                //调用BeanFactory的后处理器,这些后处理器是在Bean定义中想容器注册的
                this.invokeBeanFactoryPostProcessors(beanFactory);
                //注册Bean后处理器,在Bean创建过程中调用
                this.registerBeanPostProcessors(beanFactory);
                //对上下文中的消息源进行初始化
                this.initMessageSource();
                //初始化上下文中的事件机制
                this.initApplicationEventMulticaster();
                //初始化其他的特殊Bean
                this.onRefresh();
                //检查监听Bean并且将这些Bean向容器注册
                this.registerListeners();
                //实例化所有的(non-lazy-init)单件
                this.finishBeanFactoryInitialization(beanFactory);
                //发布容器事件,结束Refresh过程
                this.finishRefresh();
            } catch (BeansException var9) {
                if (this.logger.isWarnEnabled()) {
                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
                }
                //为防止Bean资源占用,在异常处理中,销毁已经在前面过程中生成的单件Bean
                this.destroyBeans();
                //重置'active'标志
                this.cancelRefresh(var9);
                throw var9;
            } finally {
                this.resetCommonCaches();
            }

        }
    }

这个obtainFreshBeanFactory很关键,这里面有 IoC的Resource定位和载入:

    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        //资源定位和载入,是一个抽象方法,在子类AbstractRefreshableApplicationContext中实现的方法
        this.refreshBeanFactory();
        //getBeanFactory是一个抽象方法,在子类AbstractRefreshableApplicationContext中实现的方法
        ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Bean factory for " + this.getDisplayName() + ": " + beanFactory);
        }

        return beanFactory;
    }

看看refreshBeanFactory()源码如下:

   protected final void refreshBeanFactory() throws BeansException {
       //这里判断,如果建立了BeanFactory,则销毁并关闭该BeanFactory
        if (this.hasBeanFactory()) {
            this.destroyBeans();
            this.closeBeanFactory();
        }

        try {
            //这里的创建并设置持有的DefaultListableBeanFactor的地方
            DefaultListableBeanFactory beanFactory = this.createBeanFactory();
            beanFactory.setSerializationId(this.getId());
            this.customizeBeanFactory(beanFactory);
            //载入Bean ,抽象方法,委托子类AbstractXmlApplicationContext实现
            this.loadBeanDefinitions(beanFactory);
            Object var2 = this.beanFactoryMonitor;
            synchronized(this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        } catch (IOException var5) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);
        }
    }

看看子类AbstractXmlApplicationContext中实现的loadBeanDefinitions:

 protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
        Resource[] configResources = this.getConfigResources(); //只可能为null
        if (configResources != null) { //不会走这一条路 参数类型Resource...
            reader.loadBeanDefinitions(configResources);
        }

        String[] configLocations = this.getConfigLocations();
        if (configLocations != null) { // 参数类型String... 
            reader.loadBeanDefinitions(configLocations);
        }

    }

    @Nullable
    protected Resource[] getConfigResources() {
        return null;
    }

继续往下看AbstractBeanDefinitionReader流操作类的loadBeanDefinitions,这里的流操作来实现IoC的载入:

     public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
        Assert.notNull(locations, "Location array must not be null");
        int counter = 0;
        String[] var3 = locations;
        int var4 = locations.length;

        for(int var5 = 0; var5 < var4; ++var5) {
            String location = var3[var5];
            counter += this.loadBeanDefinitions(location); //调用下面的函数
        }

        return counter;
    }

    public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
        return this.loadBeanDefinitions(location, (Set)null); //调用下面的函数
    }

    public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
        ResourceLoader resourceLoader = this.getResourceLoader();
        if (resourceLoader == null) {
            throw new BeanDefinitionStoreException("Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
        } else {
            int loadCount;
            if (!(resourceLoader instanceof ResourcePatternResolver)) {
                Resource resource = resourceLoader.getResource(location);
                loadCount = this.loadBeanDefinitions((Resource)resource);
                if (actualResources != null) {
                    actualResources.add(resource);
                }

                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
                }

                return loadCount;
            } else {
                try {
                    Resource[] resources = ((ResourcePatternResolver)resourceLoader).getResources(location);
                    loadCount = this.loadBeanDefinitions(resources);
                    if (actualResources != null) {
                        Resource[] var6 = resources;
                        int var7 = resources.length;

                        for(int var8 = 0; var8 < var7; ++var8) {
                            Resource resource = var6[var8];
                            actualResources.add(resource);
                        }
                    }

                    if (this.logger.isDebugEnabled()) {
                        this.logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
                    }

                    return loadCount;
                } catch (IOException var10) {
                    throw new BeanDefinitionStoreException("Could not resolve bean definition resource pattern [" + location + "]", var10);
                }
            }
        }
    }

loadBeanDefinitions会调用DefaultResourceLoader中的getResource:

public Resource getResource(String location) {
        Assert.notNull(location, "Location must not be null");
        Iterator var2 = this.protocolResolvers.iterator();

        Resource resource;
        do {
            if (!var2.hasNext()) {
                if (location.startsWith("/")) {
                    return this.getResourceByPath(location);
                }

                if (location.startsWith("classpath:")) {
                    return new ClassPathResource(location.substring("classpath:".length()), this.getClassLoader());
                }

                try {
                    URL url = new URL(location);
                    return (Resource)(ResourceUtils.isFileURL(url) ? new FileUrlResource(url) : new UrlResource(url));
                } catch (MalformedURLException var5) {
                    return this.getResourceByPath(location);
                }
            }

            ProtocolResolver protocolResolver = (ProtocolResolver)var2.next();
            resource = protocolResolver.resolve(location, this);
        } while(resource == null);

        return resource;
    }

可以看到,getResource又调用了子类实现的getResourceByPath方法或是子类传递过来的字符串,实现 Resource定位

整个过程就说得通了。总结起来就是,Resource资源通过最外层的实现类传进来的字符串或者直接调用getResourceByPath方法,来获取bean资源路径,然后通过AbstractBeanDefinitionReader流操作实现载入,最后通过AbstractApplicationContext的registerListeners 进行注册。这就是IoC容器的初始化过程。

其他容器的初始化过程,由上面的继承关系对比,就可以知道是差不多的,这里就不一个一个分析了。

IOC容器初始化过程 IOC容器的初始化分为三个过程实现:第一个过程是Resource资源定位。这个Resouce指的是BeanDefinition的资源定位。这个过程就是容器找数据的过程,就像水桶装水需要先找到水一样。 第二个过程是BeanDefinition的载入过程。这个载入过程是把用户定义好的Bean表示成Ioc容器内部的数据结构,而这个容器内部的数据结构就是BeanDefition。 第三个过程是向IOC容器注册这些BeanDefinition的过程,这个过程就是将前面的BeanDefit 立即下载

相关推荐

告别底噪与失真:手把手教你调校WM8988音频Codec的输入输出增益链

本文详细介绍了如何调校WM8988音频Codec的输入输出增益链,解决底噪与失真问题。从模拟输入增益、数字转换增益到输出放大增益,提供了具体的寄存器配置和调试策略,帮助开发者优化音频信号处理链,提升音质表现。

weixin_30485379的博客 362

Spring官方文档阅读(五)之IOC容器(容器的扩展点)

8.容器扩展点 通常,应用程序开发人员不需要为ApplicationContext实现类提供子类。 相反,可以通过插入特殊集成接口的实现来扩展Spring IOC容器。 接下来的几节描述了这些集成接口。 8.1使用BeanPostProcessor自定义Bean BeanPostProcessor接口定义了回调方法,您可以实施这些回调方法以提供自己的(或覆盖容器的默认值)实例化逻辑,依赖关系解析逻辑等。 如果您想在Spring容器完成实例化,配置和初始化bean之后实现一些自定义逻辑,则可以插入一个或多个自

了不起的盖茨比的博客 433

NRF24L01模块的5个常见问题及解决方案:从信号干扰到功耗优化

本文深入探讨NRF24L01无线模块在STM32开发中的5大常见问题及解决方案,包括通信距离优化、数据丢失排查、电源噪声抑制、SPI通信故障处理以及低功耗设计。通过代码示例和电路图分析,提供实用的优化策略,帮助开发者提升无线通信的稳定性和效率。

weixin_28256233的博客 226

IoC容器初始化过程

IoC容器初始化主要包括三个过程: BeanDefinition 的 Resource 定位 BeanDefinition 的载入 BeanDefinition 在 Ioc 容器中的注册 三个过程都与BeanDefinition有关,那么我们先来看一下什么是BeanDefinition 。 BeanDefinition 是 Spring 内部的一个接口,定义了 Bean 描述的基本...

Angus爱吃鱼 442

VBA一键汇总多个工作簿-名称相同的工作表-的指定区域数据

VBA一键汇总多个工作簿-名称相同的工作表-的指定区域数据 日常工作,我们经常需要汇总相同格式的工作簿的某个工作表的数据 如1月业绩、2月业绩。。。。12月业绩等 姓名 数量 数据22 22 数据23 23 数据24 24 数据25 25 数据26 26 数据27 27 数据28 28 数据29 29 数据30 30 数据31 31 数据32 32 数据33 33 数据34

陈表达的博客 5981

AI产品经理必备:Agent评测维度、指标与工程化落地指南

随着大模型从单轮问答走向复杂的Agent应用,如何科学地评测一个Agent是否真正“办成了事”,成为AI产品经理必须掌握的核心能力。与传统大模型评测关注回答质量不同,Agent评测需要综合评估任务规划、工具调用、多轮对话一致性以及失败自愈等行为。任务完成率与工具调用成功率是最关键的两个量化指标,同时还需关注延迟与Token成本等工程约束。在实际落地中,评测集的设计要覆盖业务主流程与边界场景,并通过批量回归测试与版本对比,为产品选型、算法迭代和上线决策提供数据支持。本文系统拆解了Agent评测的完整流程,帮助

weixin_29057163的博客 340

Spring学习--IOC容器的初始化过程

IOC容器初始化概述 IOC容器初始化是由refresh()

m0_47954009的博客 2292

游戏引擎揭秘:大厂为何死磕自研?

游戏引擎本质与商业价值解析 游戏引擎是集成了渲染、物理、动画等核心功能的开发工具包,其价值在于让开发者免于重复编写底层代码,专注于游戏内容创作。商业引擎(如Unity/Unreal)虽降低了开发门槛,但头部厂商仍坚持自研引擎,主要基于以下考量: 经济性:长期项目分摊自研成本后,比商业引擎分成更划算; 可控性:完全掌握底层代码,能针对性优化核心玩法需求; 技术壁垒:专属引擎成为厂商的竞争优势,如米哈游的跨平台渲染技术; 项目适配:超大型游戏(开放世界/MMO)需要深度定制解决方案。 这种"短期高投入

本博客聚焦游戏开发技巧、创业实战心得及大学热门课程干货。这里既有技术深度,也有思维广度,无论你是开发者、创业者还是高校学子,都能在这里找到适合自己的成长之路! 263

IOC容器的初始化过程

本节来学习IOC容器的初始化过程IOC容器的初始化由refresh()方法启动的,具体包含BeanDefinition的Resource定位、载入和注册三个过程。第一个过程是Resource定位过程。Resource定位指的是BeanDefinition的资源定位,由ResourceLoader通过统一的Resource接口来完成。第二个过程是BeanDefinition的载入。这个载入过程是把用...

dxh0823的专栏 554

深入剖析Zynq AMP模式下CPU1中断响应机制:从原理到创新实践

在异构计算领域,Zynq-7000系列SoC的AMP(Asymmetric Multiprocessing)模式堪称多核编程的瑞士军刀。独立运行环境:CPU0运行Linux,CPU1运行FreeRTOS或裸机程序硬件资源独占:CPU0管理DDR,CPU1使用OCM(片上内存)中断隔离:默认所有中断路由到CPU0这种架构非常适合需要实时响应的工业控制系统——比如用CPU0处理网络通信,CPU1负责电机控制。AMP模式下中断路由的底层原理多维度性能优化技巧工业级可靠性的实现方案。

QQ_778132974的博客 490

杰理AC695N/AC696N/AC701N系列芯片在线调音教程

本教程详细介绍AC695N/AC696N/AC701N芯片在线音效调试方法,包括工具准备(需安装杰理包管理器)、程序修改(需关闭USB功能并启用在线调试宏)、连接方式(USB或串口)、音效调节步骤(EQ和混响参数调整)以及配置保存。注意事项包括版本匹配、连接检查和供电稳定等,并提供常见问题解决方案。适用于快速配置实时音效调试环境并保存最终配置。

qq_42014563的博客 1400

Spring IOC容器初始化过程及其原理(源码层面)

Spring大家族在Java技术生态体系中占有重要地位,其中Spring更是其中的佼佼者。它极大的简化了我们的代码开发量,提高我们的工作效率。 其中Spring两大特性中的IOC特性是至关重要的。今天来从底层看一看Spring的容器的初始化过程。算是我的学习笔记,也希望能对你有所帮助! (如果有不懂IOC的小伙伴们可以去看一看我前面写的文章传送门在此)。 在开始之前,先思考几个问题。 @Component,@Service,@Controller,@Repository@Bean等注解怎么实现的.

m0_46405589的博客 1147

SAP-ABAP:在SAP系统中,COEP表(成本控制对象行项目表)详解

在SAP系统中,COEP表(成本控制对象行项目表)详解

baidu_35680696的博客 1837

Spring原理-IoC容器初始化过程

IoC容器初始化过程 IoC容器的两个核心接口BeanFactory和ApplicationContext大概功能都讲解了一些,接下来我们讲解一下IoC容器的初始化过程,让大家有一个深一点的理解。讲解还是以FileSystemXmlApplicationContext类作为入口进行讲解。 首先我们看一段FileSystemXmlApplicationContext类中的源码:     pub

冲吧,不要停! 3012

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Spring学习06--IOC实现原理以及IOC容器初始化过程

一、IOC原理 Spring功能如此强大,但是再强大的功能也是用java代码写出来的,那么就来看看IOC的实现原理是什么。 上一章说到,由于bean中lazy-init属性的存在,我们没有办法一次性将所有bean全部实例化,并且放到一个Mappackage org.springframework.beans.factory.support;import java.io.NotSerializab

Errol的分享空间 450

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

Spring源码解析--《SPRING技术内幕:深入解析Spring架构与设计原理》读书笔记(一):IOC容器初始化过程

通过阅读相关章节内容,Spring中IOC容器的加载中,我们需要了解下列几个概念: Resource:是一个定位、访问资源的抽象接口,包含了多种资源操作的基础方法定义,如getInputStream()、exists()、isOpen()、getDescription()等。 BeanDefinition:POJO对象在IOC容器中的抽象,通过此数据结构,使IOC容器能方便地对P...

yzy199391的博客 6781

Spring原理(一)IoC容器的初始化过程之BeanFactory

IoC容器的初始化过程 IoC容器的启动过程包括BeanDefinition的Resource定位、载入和注册三个基本过程。 但spring是把这三个过程分开的,并用不同的模块来完成,比如ResourceLoader、 BeanDefinitionReader、这种设计具有很高的灵活性,用户可以根据不同的需要组合出适合自己的初始 化过程。 第一个过程是R

北风之神的博客 4217

Spring原理(二)IoC容器的初始化过程之ApplicationContext

上一篇已经介绍了BeanFactory的初始化过程,这一篇介绍一下ApplicationContext的初始化。ApplicationContext有很多实现,这里以常见的FileSystemXmlApplicationContext为例来说明一下ApplicationContext的初始化过程。 启动ApplicationContext 以下代码就初始化了一个IoC容器,FileSyst

北风之神的博客 2236

Spring IOC 原理

Spring IOC原理IOC理解自己写的简单的IOC容器IOC的原理定位、加载、注册基于XML配置的IOC容器初始化1、寻找入口2、获取配置路径3、开始启动4、创建容器5、载入配置路径6、分配路径处理策略7、解析配合文件路径8、开始读取配置内容9、准备文档对象10、分配解析策略11、将配置载入内存12、载入元素13、载入元素14、载入的子元素15、载入的子元素16、分配注册策略17、向容器注册时...

heyanfeng22的专栏 338

Spring——Spring IOC容器初始化过程

Spring IOC容器的初始化简单的可以分为三个过程: 第一个过程是Resource资源定位。这个Resouce指的是BeanDefinition的资源定位。这个过程就是容器找数据的过程,就像水桶装水需要先找到水一样。(将xml, db.properties等文件打包成一个BeanDefinition) 第二个过程是BeanDefinition的载入过程。这个载入过程是把用户定义好的Bean表...

Stay Hungry Stay Foolish 1082

IOC容器的初始化与依赖注入过程

IOC容器个人理解终于有闲暇时间对Spring的源码展开攻势:IOC容器到底是个什么东西1.我把它看做是一个桶,具体例子有(XMLBeanDefinition、ApplicationContext)这两个都是IOC容器的具体实现。 2.这个桶implements接口BeanFactory.桶里面持有一个HashMap装的是BeanDefinition。我理解的IOC容器的实现过程1.初始化一个接口

CallmeDaChang的博客 1577

Spring IoC容器初始化过程

IoC(Inversion of Control),即控制反转,spring通过IoC容器创建bean并维护bean之间的关系,这是spring的核心,贯穿始终。它不是一项技术,而是一种思想,控制反转是相对来说的。一个A类中包含有一个B类的属性,我们认为A依赖B。}}普通情况下,我们在A对象中主动去创建依赖对象B,通过new关键字,spring是由IoC容器通过DI(Dependency Injection)方式注入依赖对象,被动获取资源,

CaptainCats的博客 887

【Spring源码解析】—— 结合SpringMVC过程理解IOC容器初始化

关于IOC容器的初始化,结合之前SpringMVC的demo,对其过程进行一个相对详细的梳理,主要分为几个部分: 一、IOC的初始化过程,结合代码和debug过程重点说明 1、 为什么要debug? 答:直接自己从源码看第一遍,会有一个初步的认识;但是看完之后,会因为没有实际走一遍执行而无法验证自己认知的过程;另外就是:因为基于接口本身会有多个实现,因此在很多情况下,通过Ctrl+B直...

weixin_30672295的博客 139

SpringFramework学习-(4)IOC容器初始化过程详解

前面一篇Spring学习-(3)我的IOC容器 自己实现了一个简陋的IOC容器。Spring的IOC容器并没有这么简单,接下来一起进入SpringIOC的世界。Spring源码探究:IoC容器初始化过程详解,该篇文章写的非常好,难度也挺大,有些内容可能并没有明确指明。在这篇文章的基础之上,做一些减速和细化,从ClassPathXmlApplicationContext类开始逐一往上分析IOC容器的

jinjin603的博客 307

透析Spring(一): Spring之IoC容器理解

看懂Spring的IoC容器设计思路,好处,并和DI进行比较等

Java学习之道 4020

Spring:源码解读Spring IOC原理

那为何要定义这么多层次的接口呢?Spring IoC容器对Bean定义资源的载入是从refresh()函数开始的,refresh()是一个模板方法,refresh()方法的作用是:在创建IoC容器前,如果已经有容器存在,则需要把已有的容器销毁和关闭,以保证在refresh之后使用的是新建立起来的IoC容器。refresh()方法的作用是:在创建IoC容器前,如果已经有容器存在,则需要把已有的容器销毁和关闭,以保证在refresh之后使用的是新建立起来的IoC容器。

2401_86940371的博客 1382
上一篇: 接口回调用法解析
下一篇: JDK动态代理机制
She_lock
博客等级 码龄12年 157粉丝 134原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值