Spring容器的IOC和DI概念

IOC(控制反转):对于组件的控制权进行了转移,传统的程序设计是由客户端new出对象,是程序主动创建所依赖的对象。而IOC是专门将对象的创建交给容器处理,组件的控制器交由到了IOC容器中。

DI(依赖注入):组件之间的依赖关系由容器在运行期决定,容器动态将某个依赖关系注入到组件中,主要为了提升组件的复用。

IOC侧重于实现了容器对于组件的管理,DI侧重于对于组件的依赖关系。

Bean加载过程

早期的Spring都是通过配置XML进行Bean加载的,过程大致如下:

  • XML是配置文件,定义了Spring标签定义;

  • Resource是Spring对于资源的抽象;

  • Document是从Resource中读取的XML定义解析为Document;

  • BeanDefinition是XML文件定义Java对象的一个过程;

  • Bean最后被实例化成Object对象;

Resource持有URL Resource,主要是为了读取XML的Resource。

读取到XML的Resource之后主要进行XML标签解析,也就是Resource -> Document -> BeanDefinition过程。

BeanDefinition是XML文档的一种表现形式。

IOC容器初始化

IOC容器初始化的核心流程主要有四个步骤:

  1. Bean定义和定位,Bean可能放在XML中,或者一个注解,这些都可以被Resource定位,读取Resource获取BeanDefinition注册到Bean定义的注册表中。

  2. 第一次想容器getBean操作会触发Bean创建过程,实例化出一个Bean,根据BeanDefinition中类信息实例化Bean。

  3. 将实例化的Bean放到单例缓存中。

  4. 之后再次获取向容器getBean时从缓存取。

Bean生命周期

Bean生命周期主要经历四个阶段:

  1. 实例化:createBeanInstance方法,主要创建BeanWrapper;

  2. 属性赋值:将BeanDefinition中属性赋值到BeanWrapper中;

  3. 初始化和setter注入:利用BeanWrapper初始化Bean实例;

  4. 销毁:注册响应销毁方法,在容器关闭时触发Bean实例销毁操作;

在Bean实例化过程中,Spring为我们预留了好多API,我们可以在Bean的实例化前后,初始化前后做一些自己的逻辑。

1. 根据BeanDefinition信息,实例化对象,Constructor构造方法;

2. 根据BeanDefinition信息,配置Bean的所有属性(将bean的引用注入到bean对应的属性,*可能存在循环依赖问题);

3. 如果Bean实现了BeanNameAware接口,工厂调用Bean的setBeanName,参数为Bean的Id;

4. 如果Bean实现BeanFactoryAware接口,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入;

5. 如果Bean实现ApplicationContextAware接口,Spring将调用setApplicationContext()方法,将bean所在的应用上下文的引用传入进来;

5. 如果存在类实现了BeanPostProcessor接口,执行这些实现类的postProcessBeforeInitialization方法,这相当于在Bean初始化之前插入逻辑  ;

6. 如果Bean实现InitializingBean接口, 执行afterPropertiesSet方法;

7. 如果Bean指定了init-method方法,就会调用该方法。例:\<bean init-method="init">  ;

8. 如果存在类实现了BeanPostProcessor接口,执行这些实现类的postProcessAfterInitialization方法,这相当于在Bean初始化之后插入逻辑  ;

9. 这个阶段Bean已经可以使用了,scope为singleton的Bean会被缓存在IOC容器中

10. 如果Bean实现了DisposableBean接口, 在容器销毁的时候执行destroy方法。

11. 如果配置了destory-method方法,就调用该方法。例:\<bean destroy-method="customerDestroy">

其他扩展接口

1.InitializingBean接口

InitializingBean接口中只有一个afterPropertiesSet方法,从方法的名称上很容易理解,这个方法是在Bean的属性都设置值后被调用,用于完成一些初始化工作。当然,在Spring的配置文件中init-method的配置也是在Bean的属性都设置值后被调用,用于完成一些初始化工作,不过在执行顺序上,接口的方法先于配置。值得注意的是,这两种方式都是用于完成一些初始化工作,所以相应的方法中不要编写一些复杂且执行时间很长的逻辑。

2.DisposableBean接口

DisposableBean接口中只有一个destroy方法,该方法会在Bean被销毁、生命周期结束之前被调用,用于做一些销毁的收尾工作。同样,在Spring的配置文件中destroy-method配置也完成同样的工作,不过在执行顺序上,接口的方法先于配置。

3.ApplicationContextAware接口

ApplicationContextAware中只有一个setApplicationContext方法。实现了ApplicationContextAware接口的类,可以在该Bean被加载的过程中获取Spring的应用上下文ApplicationContext,通过ApplicationContext可以获取Spring容器内的很多信息。

4.BeanFactoryAware接口

BeanFactoryAware接口中只有一个setBeanFactory方法。实现了BeanFactoryAware接口的类,可以在该Bean被加载的过程中获取加载该Bean的BeanFactory,同时也可以获取这个BeanFactory中加载的其它Bean。

5.FactoryBean接口

FactoryBean接口可以实现Bean实例化的个性定制,让Spring容器加载我们想要的Bean。实现了FactoryBean接口的类,可以通过实现getObject方法,实现加载我们想要的Bean。

6.BeanPostProcessor接口

BeanPostProcessor接口中有两个方法,分别为postProcessBeforeInitialization和postProcessAfterInitialization。实现了BeanPostProcessor接口的类,会在每个Bean初始化(即调用setter)之前和之后,分别调用这个类中的postProcessBeforeInitialization方法和postProcessAfterInitialization方法,实现初始化的逻辑控制。

7.InstantiationAwareBeanPostProcessor接口

InstantiationAwareBeanPostProcessor接口中,常用的方法是postProcessBeforeInstantiation和postProcessAfterInstantiation。每个Bean的实例化(即调用构造函数)之前和之后,会分别调用实现了该接口的类中的postProcessBeforeInstantiation和postProcessAfterInstantiation方法。

8.BeanFactoryPostProcessor接口

BeanFactoryPostProcessor接口中只有postProcessBeanFactory方法。实现了该接口的类,可以在Bean被创建之前,获取容器中Bean的定义信息,并且可以进行修改。实现类中的postProcessBeanFactory方法只会被执行一次,且先于BeanPostProcessor接口的方法。

Aware接口

  • LoadTimeWeaverAware:加载Spring Bean时织入第三方模块,如AspectJ

  • BootstrapContextAware:资源适配器BootstrapContext,如JCA,CCI

  • ResourceLoaderAware:底层访问资源的加载器

  • PortletConfigAware:PortletConfig

  • PortletContextAware:PortletContext

  • ServletConfigAware:ServletConfig

  • ServletContextAware:ServletContext

  • MessageSourceAware:国际化

  • ApplicationEventPublisherAware:应用事件

  • NotificationPublisherAware:JMX通知

Aware接口特点

  • 都是Aware接口的子接口,即都继承了Aware接口

  • 父接口Aware中没有定义任何方法

  • 接口内均定义了一个set方法,set参数就是我们需要获取的对象

扩展:

https://www.jianshu.com/p/f78b4b4435c2

https://www.jianshu.com/p/b3e97123fcaf

https://www.jianshu.com/p/a184b5a89850

Spring容器和Bean加载相关推荐

  1. spring技巧之bean加载顺序控制

    spring技巧之bean加载顺序控制 前言 误区 疑问 思路 关键代码示例 前言 某些时候,我们想要控制bean的加载顺序,比如某些资源配置类的bean需要在其他的bean之前被加载,以便其他bea ...

  2. spring容器的懒加载

    默认情况下,spring的IOC容器中lazy-init是false的,即没有打开懒加载模式. 如果你没有看到这个lazy-init 的参数设置就说明是false啦. 那么什么是懒加载? 懒加载--- ...

  3. spring容器的懒加载lazy-init设置

    默认情况下,spring的IOC容器中lazy-init是false的,即没有打开懒加载模式. 如果你没有看到这个lazy-init 的参数设置就说明是false啦. 那么什么是懒加载? 懒加载--- ...

  4. Spring源码分析:Bean加载流程概览及配置文件读取

    很多朋友可能想看Spring源码,但是不知道应当如何入手去看,这个可以理解:Java开发者通常从事的都是Java Web的工作,对于程序员来说,一个Web项目用到Spring,只是配置一下配置文件而已 ...

  5. 剖析Spring源码:加载IOC容器

    本文接上一篇文章 阅读Spring源码:IOC控制反转前的处理,继续进行下面的分析 首先贴出 Spring bean容器的刷新的核心 11个步骤进行祭拜(一定要让我学会了-阿门) // 完成IoC容器 ...

  6. Spring控制Bean加载顺序

    spring容器载入bean顺序是不确定的,spring框架没有约定特定顺序逻辑规范. 首先要了解depends-on或@DependsOn作用,是用来表示一个bean A的实例化依赖另一个bean ...

  7. Spring的bean加载流程

    IOC容器就像是一个工厂,里面有很多流水线生产出一个个产品(bean).bean的加载流程大概分为: 容器启动阶段 bean加载阶段 容器启动阶段: 1.配置元信息 当你生产物品的时候总得知道产品得规 ...

  8. Spring 使用注解@DependsOn控制Bean加载顺序

    文章目录 1. 前言 2. 代码实现 1. 前言 默认情况下,Spring加载Bean的顺序是不确定的(或者可以理解为,按编译后的class文件顺序加载).当我们需要控制Bean加载顺序以满足特定的需 ...

  9. 【Spring源码分析】Bean加载流程概览

    代码入口 之前写文章都会啰啰嗦嗦一大堆再开始,进入[Spring源码分析]这个板块就直接切入正题了. 很多朋友可能想看Spring源码,但是不知道应当如何入手去看,这个可以理解:Java开发者通常从事 ...

最新文章

  1. 工业视觉检测发展的现状
  2. Linux下如何查看硬件信息?
  3. 医学+数据科学,必将大有可为 | 清华生物医学影像研究中心赵锡海
  4. aix6.1安装oracle 10g总结
  5. Delphi命名规范
  6. java网络编程(二)
  7. 数据分析TB级别数据量大了怎么办,不会代码模型训练怎么办?
  8. iOS之深入解析Xcode的拼写检查
  9. MacOS下保护浏览器主页和默认搜索
  10. Python操作excel(.xlsx)封装类MyPyExcel V2.0
  11. linux如何挂载nfs目录,linux – NFS导出已经挂载NFS的目录(在服务器上)
  12. 开源文件管理服务器,GitHub - biiliwuiid/file-manager: 文件服务器管理系统
  13. 三星s3android wear,三星galaxy wearable下载
  14. Mongo数据库慢查询功能
  15. Safari浏览器(有时没有图片时,提交会出现问题)。
  16. Android4.4点击无响应,webview某些超链接点击无响应的问题
  17. 为什么模电这么难学?
  18. ASP.NET:性能与缓存 转帖 张逸老师(http://www.cnblogs.com/wayfarer/articles/48347.aspx)...
  19. hikey970开发板安装系统
  20. adb 命令与手机控制(提供python测试)

热门文章

  1. luogu P3203 [HNOI2010]弹飞绵羊(LCT ? 暴力分块 ! )
  2. 十一届蓝桥杯java组-蓝肽子序列-动态规划
  3. 计算机二级怎么更改报名密码忘记了怎么办,中考报名系统密码忘了怎么办
  4. 程序员心中都有一个江湖,java世界,就是一个江湖!
  5. Java编程基础04——流程控制语句
  6. 数据库水平切分(MyCat分片Join)
  7. vs + ffmpeg------待续
  8. 数据库被黑后留下的数据
  9. Hibernate缓存原理与策略 Hibernate缓存原理:
  10. 轻松学HTML+CSS网站开发