Spring学习(一) IoC
文章部分图片来自参考资料,本文介绍的是 Spring 的两个重要概念,是学习总结。
我们依旧提出几个问题,帮助我们在学习中带着问题解答。
问题 :
- 如何理解Ioc,它解决了什么难题(或者说是使用它的好处)
- Ioc Container 是什么
概述
IoC涉及到三个名词
- IoC (Invention Of Control ) 控制反转
- DI(Dependency Injection) 依赖注入
- IoC Container 控制反转容器
他们的关系如下图所示。

上图我们可以得出 :
控制反转是目的,而依赖注入是实现控制反转的手段。
理解这一点很重要。要始终记得控制反转这个思路是我们要追求的目的。
资料阅读
用通俗的语言来解释控制反转可以参考下面几篇文章 :
- Spring IoC有什么好处呢? - Sevenvidia的回答 - 知乎
- Spring IoC有什么好处呢? - Eric的回答 - 知乎
- Inversion of Control Containers and the Dependency Injection pattern
- wiki_di
通过前面四篇文章的阅读可以了解到控制反转的概念和可以解决到的问题, 我们下面再来总结一下几个知识点 。
IoC 和 IoC Container
IoC 主要的作用就是解耦各个组件,让高层模块不依赖底层模块,而是让两者依赖接口和抽象来实现。
ioc的思想最核心的地方在于,资源不由使用资源的双方管理,而由不使用资源的第三方管理,这可以带来很多好处。
1. 资源集中管理,实现资源的可配置和易管理。
2. 降低了使用资源双方的依赖程度,也就是我们说的耦合度
而IoC Container (控制反转容器)是通过维护一个configuration 文件初始化Bean对象的容器,它的好处 :
- 这个容器可以自动对你的代码进行初始化,你只需要维护一个Configuration(可以是xml可以是一段代码)
- 不要在乎初始化对象的细节,降低了开发的难度
依赖注入的主要作用是配置和管理我们的应用对象,依赖注入的方式有 :
- 构造方法注入
- 接口注入
- setter 方法注入
bean 在容器中的管理
bean 在Ioc Container 中,那么容器中如何注入和管理的又是谁?我们又是如何从容器中获取出来bean的呢?容器的管理者正是 BeanFactory ,而获取管理的bean自然需要一个上下文对象 : ApplicationContext
下面将会介绍BeanFactory和ApplicationContext这两者的知识点,并介绍了 FactoryBean
BeanFactory 和 ApplicationContext
BeanFactory 和 ApplicationContext 两者都是接口,前者提供了一个高级的机制去管理任何类型的对象(bean);后者是 BeanFactory的子接口,它增加多了以下功能 :
• 更轻松地与Spring的AOP功能集成
• 消息资源处理(用于国际化)
• 事件发布
• 特定于应用程序层次的上下文,例如WebApplicationContext,用于Web应用程序
下面这一段这是关于 BeanFactory的介绍。
The
BeanFactoryAPI provides the underlying basis for Spring’s IoC functionality. Its specific contracts are mostly used in integration with other parts of Spring and related third-party frameworks, and itsDefaultListableBeanFactoryimplementation is a key delegate within the higher-levelGenericApplicationContextcontainer.
BeanFactoryand related interfaces (such asBeanFactoryAware,InitializingBean,DisposableBean) are important integration points for other framework components. By not requiring any annotations or even reflection, they allow for very efficient interaction between the container and its components.
总而言之,BeanFactory 提供了配置框架和基础的功能,而 ApplicationContext 添加了更多与企业级别相关的功能,ApplicationContext 是BeanFactory 的全子集,提供了很多 BeanFactory 所不及的功能。下图列举了这两种接口可以完成的功能对比 :

应用上下文( ApplicationContext)
Spring自带了多种类型的应用上下文。 下面罗列的几个是你最有可能遇到的。
- AnnotationConfigApplicationContext: 从一个或多个基于Java的配置类中加载Spring应用上下文。
- AnnotationConfigWebApplicationContext: 从一个或多个基于Java的配置类中加载Spring Web应用上下文。
- ClassPathXmlApplicationContext: 从类路径下的一个或多个XML配置文件中加载上下文定义, 把应用上下文的定义文件作为类资源。
- FileSystemXmlapplicationcontext: 从文件系统下的一个或多个XML配置文件中加载上下文定义。
- XmlWebApplicationContext: 从Web应用下的一个或多个XML配置文件中加载上下文定义。
这些都是 ApplicationContext 的子类,这些子类在不同场景发挥着作用。(从名字我们就可以判断在哪些场景了)
FactoryBean
FactoryBean 是个接口,它的作用是返回一些真实需要的bean,即是说某些bean并不能一步到位可以注入到Container ,需要经过特殊的构造,它的常见的子类实现是 : ProxyFactoryBean 和 JndiRmiProxyFactoryBean 。 从它的子类,我们就可以知道FactoryBean 对于一些有特定要求的Bean 解决这一痛点发挥着作用。
public interface FactoryBean<T> {
@Nullable
T getObject() throws Exception;
@Nullable
Class<?> getObjectType();
default boolean isSingleton() {
return true;
}
}
从上面的解释中好难理解 FactoryBean 真实的作用是什么(开始看到这个东西的时候)。推荐阅读这两篇资料 : fb_doc 和 what's the fb ,资料讲到的 FactoryBean 的作用 :
A
FactoryBeanis a pattern to encapsulate interesting object construction logic in a class. It might be used, for example, to encode the construction of a complex object graph in a reusable way. Often this is used to construct complex objects that have many dependencies. It might also be used when the construction logic itself is highly volatile and depends on the configuration. AFactoryBeanis also useful to help Spring construct objects that it couldn’t easily construct itself. For example, in order to inject a reference to a bean that was obtained from JNDI, the reference must first be obtained. You can use theJndiFactoryBeanto obtain this reference in a consistent way. You may inject the result of aFactoryBean’sgetObject()method into any other property.
第二篇文章用到一个示例代码,如下 :
public class Person {
private Car car ;
private void setCar(Car car){ this.car = car; }
}
public class MyCarFactoryBean implements FactoryBean<Car>{
private String make;
private int year ;
public void setMake(String m){ this.make =m ; }
public void setYear(int y){ this.year = y; }
public Car getObject(){
// wouldn't be a very useful FactoryBean
// if we could simply instantiate the object!
CarBuilder cb = CarBuilder.car();
if(year!=0) cb.setYear(this.year);
if(StringUtils.hasText(this.make)) cb.setMake( this.make );
return cb.factory();
}
public Class<Car> getObjectType() { return Car.class ; }
public boolean isSingleton() { return false; }
}
<bean class = "a.b.c.MyCarFactoryBean" id = "car">
<property name = "make" value ="Honda"/>
<property name = "year" value ="1984"/>
</bean>
<bean class = "a.b.c.Person" id = "josh">
<property name = "car" ref = "car"/>
</bean>
//或是 javaConfig 的形式
// identical configuration in Java to the XML above
@Configuration
public class CarConfiguration {
@Bean
public MyCarFactoryBean carFactoryBean(){
MyCarFactoryBean cfb = new MyCarFactoryBean();
cfb.setMake("Honda");
cfb.setYear(1984);
return cfb;
}
@Bean
public Person aPerson(){
Person person = new Person();
person.setCar( carFactoryBean().getObject());
return person;
}
}
上面的示例可以看到,返回的bean 对象并不是 FactoryBean ,而是经过“封装”过后的对象,这正是FactoryBean 的作用。
FactoryBean 和其他Spring Bean 一样也是享有同样的 lifecycle hooks 和 services(like AOP) ,所以当你想要在设置属性之前,让spring container 返回一个回调给你也是行的,只要继承 InitializingBean 接口。详细地见下面引用,来自第二篇推荐文章 :
Spring
FactoryBeans have all the other characteristics of any other Spring bean, including the lifecycle hooks and services (like AOP) that all beans in the Spring container enjoy.So, if you’d like a chance to perform construction logic after the properties on the
FactoryBeanhave been set, but before thegetObject()method has been called, then you can tell the Spring container give yourFactoryBeana callback. One way to do this is to implement theInitializingBeaninterface. This will be called no matter what. A far more POJO-centric alternative is to annotate a method with@PostConstruct. This method will be called, in this case, after both the code>make and theyearproperties have been set. You might use this callback to do sanity checks before the object construction’s finished, but after the configuration by the container has finished.
@PostConstruct
public void setup() throws Throwable {
// these methods throw an exception that
// will arrest construction if the assertions aren't met
Assert.notNull(this.make, "the 'make' must not be null") ;
Assert.isTrue(this.year > 0, "the 'year' must be a valid value");
}
参考资料
Spring学习(一) IoC的更多相关文章
- Spring学习之Ioc控制反转(1)
开始之前: 1. 本博文为原创,转载请注明出处 2. 作者非计算机科班出身,如有错误,请多指正 ---------------------------------------------------- ...
- Spring学习之Ioc控制反转(2)
开始之前: 1. 本博文为原创,转载请注明出处 2. 作者非计算机科班出身,如有错误,请多指正 ---------------------------------------------------- ...
- Spring学习笔记IOC与AOP实例
Spring框架核心由两部分组成: 第一部分是反向控制(IOC),也叫依赖注入(DI); 控制反转(依赖注入)的主要内容是指:只描述程序中对象的被创建方式但不显示的创建对象.在以XML语言描述的配置文 ...
- Spring 学习笔记 IoC 基础
Spring IoC Ioc 是什么 IoC -- Inversion of Control(控制反转)什么是控制?什么是反转? 控制反转了什么? 在很早之前写项目不用 Spring 的时候,都是在 ...
- Spring学习之Ioc
Ioc原理讲解:http://www.cnblogs.com/xdp-gacl/p/4249939.html Ioc IoC是一种编程思想,由主动编程变为被动接收. 也就是说,所有的组件都是被动的(p ...
- [跟我学spring学习笔记][IoC]
IoC基础 什么是IoC Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想. ioc做什么 IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找 ...
- spring学习(一) ———— IOC讲解
spring基本就两个核心内容,IOC和AOP.把这两个学会了基本上就会用了. --WH 一.什么是IOC? IOC:控制反转,通俗点讲,将对象的创建权交给spring,我们需要new对象,则由spr ...
- spring 学习 二 IOC/DI
中文名称:控制反转 英文名称:( Inversion of Control ) 1 控制反转作用: 一般在编写java程序时,需要程序员自己创建对象的实例,例如 A a=new A();语句,就是程序 ...
- Spring学习二----------IOC及Bean容器
© 版权声明:本文为博主原创文章,转载请注明出处 接口 用于沟通的中介物的抽象化 实体把自己提供给外界的一种抽象化说明,用以由内部操作分离出外部沟通方法,使其能被修改内部而不影响外界其他实体与其交互的 ...
- Spring学习之==>IoC
一.概述 Spring的三大核心思想:IoC(控制反转),DI(依赖注入),AOP(面向切面编程).本问讲着重介绍一下控制反转. 何谓控制反转:Spring 通过一种称作控制反转(IoC)的技术促进了 ...
随机推荐
- android 中如何模拟back键
主要是在使用Fragment时能够返回前一级,所以才找到了这些资料. 有两种方式可以实现,直接上代码 方法1: public void onBack(){ new Thread(){ public v ...
- Mysql 图形工具 Navicat
Navicat 在生产环境中操作MySQL数据库还是推荐使用命令行工具mysql,但在我们自己开发测试时,可以使用可视化工具Navicat,以图形界面的形式操作MySQL数据库 官网下载:https: ...
- C语言 算平均数
int main() { int number ; int sum = 0; int count = 0; do { scanf("%d", &number ); if( ...
- 用IDA辅助分析grub的小技巧
IDA可以辅助我们分析grub的代码,但是bootloader本身只是bin文件,为了让IDA能正确识别分析,我们还需要提供一些基本的参数,比如文件加载到内存的地址等. 图中MBR是加载到0x7C00 ...
- 2016级算法第一次练习赛-A.群鸦的盛宴
858 群鸦的盛宴 题目链接:https://buaacoding.cn/problem/858/index 思路 本题乍一眼看过去,你可能会想到使用一个二维数组A[51][51]来记录从i到j的路线 ...
- centOS7虚拟机设置固定IP
说明:想要达到的如下效果, 1.笔记本主机IP为设置自动获取,不管什么情况下,不受虚拟机影响,只要连接外网就可以正常上网: 2.只要笔记本主机可以正常访问外网,启动虚拟机中的CentOS 7系统就 ...
- UML-6.1-用例-示例
1.总览要点:用例.摘要.非正式.详述.测试用例.用例分析与迭代联系起来. 2.示例:Process Sale 1).客户携带所购商品到达收银台. 2).收银员使用pos系统记录每件商品. 操作契约: ...
- 使用Jmeter进行http接口性能测试(转载)
在进行网页或应用程序后台接口开发时,一般要及时测试开发的接口能否正确接收和返回数据,对于单次测试,Postman插件是个不错的Http请求模拟工具. 但是Postman只能模拟单客户端的单次请求,而对 ...
- pandas数据清洗
1.我已安装好Anavonda3.5.所以我只用打开"jupyter notebook",然后打开浏览器 然后点击右侧的“new",然后打开python3
- java多线程-线程间协作
大纲: wait.notify.notifyAll Condition 生产消费者 一.wait.notify.notifyAll wait.notify.notifyAll是Object的本地fin ...