- java垃圾回收机制帮助咱们实现了这个过程;
- 而ioc则是让咱们无需考虑对象的建立过程,由ioc容器帮咱们实现对象的建立、注入等过程。
【说明】:java
Contextweb
- 对于IoC和DI的理解
- BeanFactory
- ApplicationContext
Bean数据库
- SpEL(#)
- 引入外部的属性文件($)
基于XML的Bean配置编程
配置Bean设计模式
- 经过全类名
- 经过工厂方法
- 经过 FactoryBean
装配Bean的属性安全
- 经过属性
- 经过构造器
基于注解的Bean配置架构
装配Bean的属性app
- Autowired等注解
配置Bean框架
- Context:componentScan节点
图片描述
【说明】:工具
IoC 概念
- 应用控制反转,对象在建立的时候,由一个调控系统内全部对象的外界实体,将其所依赖的对象的引用,传递给它。也能够说,依赖注入到对象中。因此,控制反转是,关于一个对象如何获取他所依赖的对象的引用,这个责任的反转。
- 控制反转(Inversion of Controll)是一个重要的面向对象编程的法则,来削弱计算机程序的耦合问题,也是轻量级 Spring 框架的核心。
- 控制反转通常分为两种类型,依赖注入(Dependency Injection,DI)和依赖查找(Dependency Lookup),依赖注入应用普遍。
深刻分析
- 依赖于谁?应用程序依赖于 IoC 容器
- 为何要依赖?应用程序须要 IoC 容器来提供对象须要的外部资源
- 谁注入谁?IoC容器注入应用程序某个对象,应用程序依赖的对象
- 注入了社么?注入某个对象所须要的外部资源(包括对象、资源、常量对象)
与new对象的区别
- 正转与反转,传统应用程序是由咱们将本身在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮助建立及注入依赖对象。
IoC优缺点
- 优势:实现组件之间的解耦,提供程序的灵活性和可维护性
- 缺点:对象生成由于是使用反射编程,在效率上有损耗
2、Spring IoC 容器
【Spring核心组件】:它们构建起了整个Spring的骨骼架构,没有它们就不可能有AOP、Web等特性功能。
- Core
- Context
- Bean
Spring解决了一个很是关键的问题,它可让你对对象之间的关系转而用配置文件来管理,或者注解,也就是它的依赖注入机制。而这个注入关系在一个叫Ioc的容器中管理。Ioc容器就是被Bean包裹的对象。Spring正是经过把对象包装在Bean中从而达到管理这些对象及作一些列额外操做的目的。
- 概念:
在每一个框架中都有一个容器的概念,所谓的容器就是将经常使用的服务封装起来,而后,用户只须要遵循必定的规则,就能够达到统1、灵活、安全、方便、快速的目的
具备依赖注入功能的容器,负责实例化、定位、配置应用程序中的对象及创建这些对象间的依赖
- Bean的概念:
由IoC容器管理的那些组成应用程序的对象就叫Bean
Bean就是由Spring容器初始化、装配及管理的对象,除此以外,Bean就与应用程序中的其余对象没什么区别了
- 元数据 BeanDefinition
肯定如何实例化Bean、管理Bean之间的依赖关系及管理Bean,就须要配置元数据,在Spring中由BeanDefintion表明
如何工做(以XML配置方式解释)
- 准备配置文件:配置文件中声明 Bean 定义也就是 Bean 配置元数据。
- 由 IoC 容器进行解析元数据:IoC 容器的 Bean Reader 读取并解析配置文件,根据定义生成 BeanDefintion 配置元数据对象,IoC 容器根据 BeanDefintion 进行实例化、配置及组装 Bean。
- 实例化 IoC 容器:由客户端实例化容器,获取须要的 Bean。
- hello world
@Test public void testHelloWorld() { // 一、读取配置文件实例化一个 IoC 容器 ApplicationContext context = new ClassPathXmlApplicationContext("helloWorld.xml"); // 二、从容器获取 Bean,主次此处彻底“面向接口编程” HelloApi helloApi = context.getBean("hello", HelloApi.class); // 三、执行业务逻辑 helloApi.sayHello(); }
三、Spring IoC 容器工做原理
- Bean : 【演员】Spring 的 bean 实例
- Context :【导演】Spring 的上下文
Bean 包装的是 Object,而 Object 必然有数据,如何给这些数据体提供生存环境就是 Context 要解决的问题,对 Context 来讲就是要发现每一个 Bean 之间的关系,为它们创建这种关系并维护关系,因此 Context 就是 Bean 关系的集合,这个关系机构叫作 IoC 容器。
- Core :【道具】Spring 的核心工具包
创建和维护每一个 Bean 之间的关系所须要的一些核心工具包。至关于 Util。
IoC 中最核心的接口是 BeanFactory 提供 IoC 的高级服务,而 ApplicationContext 是创建在 BeanFactory 基础之上提供抽象的面向应用的服务。
- BeanFactory
提供了一种先进的配置机制来管理任何种类 Bean 对象,这种配置机制考虑到任何一种可能的存储方式。
- ApplicationContext
创建在 BeanFactory,具备 BeanFactory 的全部功能和行为
- MessageSource,提供国际化的消息服务,扩展类 MessageResource 接口
- 资源访问,如 URL 和文件
- 事件传播
- 载入多个(有继承关系)上下文,使得每个上下文都专一于一个特定的层次,好比应用的 web 层。
不一样点
选用哪一个?
- BeanFactory:是延迟加载,若是 Bean 的某一个属性没有注入,BeanFactory 加载后,直至第一次使用调用 getBean 方法才会抛出异常
- ApplicationContext:则在初始化自身时检验,这样有利于检查所依赖属性是否注入;因此一般状况下使用 ApplicationContext。
特性表 BeanFatory / ApplicationContext
* Bean 实例化/装配 YES YES * 启动 BeanPostProcessor注册 NO YES * 启动 BeanFactoryPostProcessor注册 NO YES * 便捷的 MessageSource反问(i18n) NO YES * ApplicationEvent 发送 NO YES
关系
* BeanFactory 提供了配置框架和基本的功能 * ApplicationContext 创建在 BeanFactory 之上,并增长了其余功能 * 通常来讲,ApplicationContext 是 BeanFactory 的彻底超集,任何 BeanFactory 功能和行为的描述也一样被认为适用于 ApplicationContext。
在Spring框架中,依赖注入(DI)的设计模式是用来定义对象彼此间的依赖。使用xml配置bean的状况下,它主要有两种类型:
- Setter 方法注入
- 构造器注入
- 注解 @autowired
固然,有了注解以后,使用注解的方式更加方便快捷。即自动装配功能实现属性自动注入(@autowire)。
当运行 ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
构造方法 ClassPathXmlApplicationContext(String configLocation), 调用了 this(new String[] {configLocation}, true, null); 该构造方法具体代码:
【ClassPathXmlApplicationContext构造方法】:
/** * 在 parent 下建立 ClassPathXmlApplicationContext, * 从 XML 中读取素有 Bean 定义。 * @param configLocations 配置文件路径如 c:\simpleContext.xml * @param refresh 是否须要自动刷新 context,refrest--> 从新加载 * 加载全部的 bean 定义,建立全部单例。 * refresh 为 true 的时候,根据 context 来手工刷新 * @param parent the parent context * @throws BeansException if context creation failed * @see #refresh() */ public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException{ // 初始化XmlApplicationContext super(parent); // 转换配置文件的路径 setConfigLocations(configLocations); if(refresh) { // 从新刷新全部的 context,这一篇的重点 refresh(); } }
【refresh方法】:
/** * 加载或刷新持久的配置,多是xml文件,properties文件,或者关系型数据库的概要。 * 做为一启动方法,若是初始化失败将会销毁已经建立好的单例,避免重复加载配置文件。 * 换句话说,在执行这个方法以后,要不所有加载单例,要不都不加载。 public void refresh() throws BeansException, IllegalStateException { synchronized(this.startupShutdownMonitor) { // 初始化配置准备刷新,验证环境中的一些必选参数 prepareRefresh(); // 告诉继承销毁内部的 factory建立新的 factory 实例 // 初始化 Bean 实例 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 初始化 beanFactory 的基本信息,包括 classLoader、environment、忽略的注解等。 prepareBeanFactory(beanFactory); try { // beanFactory 内部的 postProces,能够理解为 context 中的 PostProcess 的补充 beanFactory.postProcessBeanFactory(beanFactory)p; // 执行 BeanFactoryPostProcessor(在beanFactory)初始化过程当中,bean 初始化以前,修改BeanFactory 参数 // BeanDefinitionRegistryPostProcessor 其实也是继承自 BeanFactoryPostProcessor, // 多个对 BeanDefinitionRegistry 的支持 invokeBeanFactoryPostProcessors(beanFactory) // 执行 postProcess,那 BeanPoseProcessor 是什么呢,是为了在 bean 加载过程当中修改 bean 的内容, // 使用Before、After分别对应初始化前和初始化后 registerBeanPostProcessors(beanFactory); // 初始化 MessageSource,主要用于 I18N 本地化的内容 initMessageSource(); // 初始化事件广播 ApplicationEventMulticaster,使用观察者模式,对注册的 ApplicationEvent 时间进行捕捉 initApplicationEventMulticaster(); // 初始化特殊的 bean 方法 onRefresh(); // 将全部 ApplicationEventListener 注册到 ApplicationEventMulticaster 中 registerListeners(); // 初始化全部部位 lazy-init 的bean,singleton 实例 finishBeanFactoryInitialization(beanFactory); // 初始化 lifeCycle 的bean启动(例如 quartz 的定时器),若是开启 JMX 则将 ApplicationContext 注册到上面 finishRefresh(); } catch(BeansException ex) { // 销毁已经建立单例 resources.destroyBeans(); // 将 context 的状态转换为无效,标示初始化失败 flag.cancelRefresh(ex); } } }
【容器初始化时序图】: