IoC(Inverse of Control,控制反转)是Spring容器的内核,AOP、声明式事务等功能在此基础上开花结构。不过IoC确实包括不少内涵,涉及代码解耦、设计模式、代码优化等问题的考量。java
先来说下以下场景:面试
《墨攻》中有个场景,刘德华饰演的墨者革离来到梁国城下,梁国守卫问道:“来者何人?”刘德华回答:“墨者革离”。设计模式
有以下几种代码实现方式:缓存
其实能够这么理解:饰演革离人物角色的,有多种选择,不必定是刘德华,这个控制权掌握在导演手里,因此最终的图示关系就是以下图:安全
那究竟是什么东西的“控制”被“反转”了呢?对应到前面的例子,“控制”是指选择GeLi角色扮演者的控制权;“反转”是指这种控制权从《墨攻》剧本中移除,转交到导演受众。对于软件来讲,即某一接口具体实现类的选择控制权从调用类中移除,转交到第三方决定,即由Spring容器借由Bean配置来进行控制。session
控制反转仍是比较晦涩难懂,那么软件界的泰斗级人物Martin Fowler提出了DI(Dependency Injection,依赖注入)的概念来代替IoC。架构
1.1 IoC的类型并发
1. 构造函数注入框架
2. 属性注入异步
3. 接口注入
1.2 经过容器完成依赖关系的注入
所谓媒体“海选”和第三方代理机构,在程序领域就是一个第三方的容器,他帮助完成类的初始化与装配工做,让开发者从这些底层实现类的实例化、依赖关系装配等工做中解脱出来,专一于更有意义的业务逻辑开发工做。这无疑是一件使人向往的事情。Spring就是这样的一个容器,它经过配置文件或注解描述类和类之间的依赖关系,自动完成类的初始化和依赖注入工做。
Java语言容许经过程序化的方式间接对Class进行操做。Class文件由类装载器装载后,在JVM中奖造成一份描述Class结构的元信息对象,经过该元信息对象能够获知Class的结构信息,如构造函数、属性和方法等。Java容许用户借由这个与Class相关的元信息对象间接调用Class对象的功能,这就为使用程序化方式操做Class对象开辟了途径。
2.1 类装载器 ClassLoader
1. 类装载器的工做机制
类装载器把一个类装入JVM中,须要通过一下步骤:
(1)装载:查找和导入Class文件
(2)连接:执行校验、准备和解析步骤,其中解析步骤是能够选择的。
1. 校验:检查载入Class文件数据的正确性。
2. 准备:给类的静态变量分配存储空间。
3. 解析:将符号引用转换成直接引用。
(3)初始化:对类的静态变量、静态代码块执行初始化工做。
2.2 Java反射机制
Java的反射体系保证了能够经过程序化的方式访问目标类中的全部的元素,对于private或protexted成员变量和方法,只要JVM的安全机制容许,也能够经过反射进行调用。
架构师圈子:142019080
JDK所提供的访问资源的类(如 java.net.URL、FIle等)并不能很好的知足各类底层资源的访问需求,好比缺乏从类路径或者Web容器上下文获取资源的操做类,鉴于此,Spring设计了一个Resource接口,它为应用提供了更强的底层资源访问能力。
Spring 经过一个配置文件描述Bean及Bean之间的依赖关系,利用Java语言的反射功能实例化Bean并创建Bean之间的依赖关系。Spirng的IoC容器在完成这些底层工做的基础上,还提供了Bean实例缓存、生命周期管理、Bean实例代理、事件发布、资源装载等高级服务。
咱们通常称BeanFactory为IoC容器,而称ApplicationContext为应用上下文。但有时为了行文方便,咱们也将ApplicationContext称为Spring容器。
BeanFactory是Spring框架的基础设施,面向Spring自己;ApplicaitonContext面向使用Spring框架的开发者,几乎全部的应用场合均可以使用ApplicationContext而非底层的BeanFactory。
4.1. 初始化BeanFactory
1) 对于单实例的Bean来讲,BeanFactory会缓存Bean实例,因此第二次使用getBean()获取Bean时,将直接从IoC容器的缓存中获取Bean实例。
2) 在Spring中,DefaultSingletonBeanRegistry类中提供了一个用于缓存单实例Bean的缓存器,它是一个用HashMap实现的缓存器,单实例的Bean以beanName为键保存在这个HashMap中。
3) 在初始化BeanFactory时,必须提供一种日志框架
4.2 ApplicationContext介绍
若是说BeanFactory是Spring的“心脏”,那么ApplicationContext就是完整的“身躯”了。
1. ApplicationContext类体系结构,它是一个接口,代码以下:
public interface ApplicationContext extends ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver { String getId(); String getDisplayName(); long getStartupDate(); ApplicationContext getParent(); AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException; }
1)ApplicationEventPublisher: 让容器拥有发布应用上下文事件的功能,包括容器启动事件、关闭事件。
2)MessageSource: 为应用提供i18n国际化消息访问的功能
3)ResourcePatternResolver: 全部ApplicationContext实现类都实现了相似于PathMatchingResourcePatternResolver的功能,能够经过带前缀的Ant风格的资源文件路径装载Spring的配置文件。
4)LifeCycle: 该接口提供了start()和stop()两个方法,主要用于控制异步处理过程。架构师圈子:142019080
初始化ApplicationContext的几种方式:
1)若是配置文件放置在类路径下,则能够优先考虑使用ClassPathXmlApplicationContext实现类
2)若是配置文件放置在文件系统的路径下,则能够优先考虑使用FileSystemXml
3)基于注解的配置方式以下:
4)基于Groovy DSL来配置Bean
2. WebApplicationContext类体系结构
在非Web应用的环境下,Bean只有singletom和prototype两种做用域。WebApplicationContext为Bean添加了三个新的做用域:request、session和global session.
ConfigurableWebApplicationContext扩展了WebApplicationContext,它容许经过配置的方式实例化WebApplicationContext,同时定义了两个重要的方法。
setServletContext(ServletContext context):为Spring设置Web应用上下文,以便两者整合。
setConfigLocations(String[] configLocation): 设置Spring配置文件地址。
3. WebApplicationContext初始化
1)使用配置文件
2)使用注解的方式
3)使用Groovy DSL的方式
4.3 父子容器
经过HierarchicalBeanFactory接口,Spring的IoC容器能够创建父子层级关联的容器体系,子容器能够访问如容器中的Bean,可是父容器不能访问自容器中的Bean。
例如:Spring使用父子容器实现不少功能,好比在Spring MVC中,展示层Bean位于一个子容器中,而业务层和持久层Bean位于如容器中。这样,展示层Bean就能够引用业务层和持久层Bean,而业务层和持久层Bean则看不到展示层Bean。
Spring为Bean提供了细致周全的生命周期过程,经过实现特定的接口或经过<bean>属性设置,均可以对Bean的生命周期过程施加影响。Bean的生命周期不但和其实现的接口相关,还与Bean的做用范围有关。为了让Bean绑定在Spring框架上,咱们推荐使用配置方式而非接口方式进行Bean生命周期的控制。
若是对java微服务、分布式、高并发、高可用、大型互联网架构技术、面试经验交流。
能够加我架构师圈子:142019080 领取资料,里面天天更新资料,免费领取。