一、 IoC概述
IoC(Inverse of Control,控制反转)是Spring容器的内核,AOP、声明式事务等功能在此基础上开花结构。不过IoC确实包括很多内涵,涉及代码解耦、设计模式、代码优化等问题的考量。
先来讲下如下场景:
《墨攻》中有个场景,刘德华饰演的墨者革离来到梁国城下,梁国守卫问道:“来者何人?”刘德华回答:“墨者革离”。
有如下几种代码实现方式:
其实可以这么理解:饰演革离人物角色的,有多种选择,不一定是刘德华,这个控制权掌握在导演手里,所以最终的图示关系就是如下图:
那到底是什么东西的“控制”被“反转”了呢?对应到前面的例子,“控制”是指选择GeLi角色扮演者的控制权;“反转”是指这种控制权从《墨攻》剧本中移除,转交到导演受众。对于软件来说,即某一接口具体实现类的选择控制权从调用类中移除,转交到第三方决定,即由Spring容器借由 Bean 配置来进行控制。
控制反转还是比较晦涩难懂,那么软件界的泰斗级人物Martin Fowler提出了DI(Dependency Injection,依赖注入)的概念来代替IoC。
1.1 IoC的类型
1. 构造函数 注入
2. 属性注入
3. 接口注入
1.2 通过容器完成依赖关系的注入
所谓媒体“海选”和第三方代理机构,在程序领域就是一个第三方的容器,他帮助完成类的初始化与装配工作,让开发者从这些底层实现类的 实例化 、依赖关系装配等工作中解脱出来,专注于更有意义的业务逻辑开发工作。这无疑是一件令人向往的事情。Spring就是这样的一个容器,它通过配置文件或注解描述类和类之间的依赖关系,自动完成类的初始化和依赖注入工作。
二、 相关 Java 基础知识
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的安全机制允许,也可以通过反射进行调用。
粉丝福利,需获取 HashMap 、分布式、微服务、spring全家桶等最新相关架构资料
关注我+转发此文+私信回复关键词: 架构
三、 资源抽象接口
JDK所提供的访问资源的类(如 java.net.URL、FIle等)并不能很好的满足各种底层资源的访问需求,比如缺少从类路径或者Web容器上下文获取资源的操作类,鉴于此,Spring设计了一个Resource接口,它为应用提供了更强的底层资源访问能力。
四、 BeanFactory 和 ApplicationContext
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()两个方法,主要用于控制异步处理过程。
初始化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。
五、BeanFactory中的Bean的生命周期
Spring为Bean提供了细致周全的生命周期过程,通过实现特定的接口或通过<bean>属性设置,都可以对Bean的生命周期过程施加影响。Bean的生命周期不但和其实现的接口相关,还与Bean的作用范围有关。为了让Bean绑定在Spring框架上,我们推荐使用配置方式而非接口方式进行Bean生命周期的控制。
粉丝福利,需获取HashMap、分布式、微服务、spring全家桶等最新相关架构资料
关注我+转发此文+私信回复关键词: 架构