水晶帘动微风起,满架蔷薇一院香。java
在软件工程中,控制反转(IoC
)是一种设计思想,对象之间耦合在一块儿,在运行时自动绑定,而且它们编译时对所须要引用的对象是不肯定的。在这个spring
教程中,经过示例了解ioc
和spring
中的依赖注入之间的区别。面试
在传统面向对象设计的软件系统中,它的底层由N多个对象构成,各个对象之间经过相互合做。最终实现业务流程。控制反转意指把建立和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,因此对象与对象之间是松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得很是灵活,尽管有些人认为使用服务定位器模式也能够提供控制反转。spring
使用控制反转做为设计准则有如下优势:编程
IoC
是一种设计范例,其目标是对应用程序的各个组件提供更多控制,使这些组件能够完成工做。依赖注入是一种模式,用于建立对象依赖的对象实例,且在编译时期是无感知的。IoC
依赖于依赖注入,由于它须要一种机制来建立且引用须要的组件。设计模式
这两个概念以这种方式协同工做,容许编写更灵活、可重用和封装的代码。所以,它们是设计面向对象解决方案的重要概念。微信
在面向对象的编程中,有几种基本技术能够实现控制反转。以下:框架
org.springframework.beans
和org.springframework.context
包为Spring
框架的IoC
容器提供了基础功能。BeanFactory
接口提供了更高级的配置项,可以管理全部对象。ApplicationContext
接口创建在BeanFactory
之上(它是一个子接口),并添加了其余功能,例如与Spring
的AOP
功能的更轻松集成,消息资源处理(用于国际化),事件传播以及特定于应用程序层的上下文,例如做为Web
应用程序中使用的WebApplicationContext
异步
BeanFactory
是Spring IoC
容器的主要实现,负责包含和管理上述Bean
。BeanFactory
接口是Spring
中的重要的IoC
容器接口。函数
BeanFactory
接口有许多实现。最经常使用的BeanFactory
实现是XmlBeanFactory
类。其余经常使用的类是XmlWebApplicationContext
。根据bean
的定义,工厂将返回所包含对象的不一样实例(Prototype
设计模式),或者返回单个共享实例(Singleton
设计模式,其中实例是做用域中的单例)。的工厂)。将返回哪一种类型的实例取决于bean
工厂的配置:获取bean
实例的API
是相同的。学习
在深刻研究依赖注入类型以前,首先肯定在spring
框架中建立bean
的方式,由于它将有助于理解下一部分的内容。
Bean
定义能够看做是建立一个或多个实际对象的配置。获取时,容器会查看命名bean
的配置,并使用该bean
定义封装的配置项来建立(或获取)实际对象。
当使用构造函数方法建立bean
时,全部普通类均可以被Spring
使用并与之兼容。也就是说,正在建立的类不须要实现任何特定的接口或以特定的方式进行编码。仅指定bean
类就足够了。使用基于XML
的配置项时,能够像这样指定bean
类:
<bean id="exampleBean" class = "cn.howtodoinjava.ExampleBean"/>
复制代码
在定义要使用静态工厂方法建立的bean
以及指定包含静态工厂方法的类的class
属性时,须要另外一个名为factory-method
的属性来指定工厂方法自己的名称。
<bean id="exampleBean" class = "cn.howtodoinjava.ExampleBean" factory-method="createInstance"/>
复制代码
Spring
但愿可以调用此方法并返回一个可用的对象,获得对象以后,该对象将被视为是经过构造函数建立的。
以相似于经过静态工厂方法进行实例化的方式,使用实例工厂方法进行实例化是调用容器中现有bean
的factory
方法来建立新bean
。
<bean id="myFactoryBean" class="cn.howtodoinjava.MyFactoryBean">
<bean id="exampleBean" factory-bean="myFactoryBean" factory-method="createInstance"></bean>
复制代码
依赖项注入(DI
)背后的基本原则是,对象仅经过构造函数参数、工厂方法的参数或属性来定义它们的依赖项,这些参数是在对象实例被构造或从工厂方法返回后在对象实例上配置的。而后,容器的工做是在建立bean时实际注入这些依赖项。即由IoC
容器帮对象找相应的依赖对象并注入,而不是由对象主动去找,所以称为控制反转(IoC
)。
经过调用无参数构造函数或无参数静态工厂方法以实例化bean
以后,在bean
上调用setter
方法,能够实现基于setter
的DI
。
public class TestSetterDI {
DemoBean demoBean = null;
public void setDemoBean(DemoBean demoBean) {
this.demoBean = demoBean;
}
}
复制代码
基于构造函数的DI
是经过调用具备多个参数(每一个参数表明一个对象实例)的构造函数来实现的。另外,调用带有特定参数的静态工厂方法来构造Bean
几乎是等效的,本文的其他部分将相似地考虑构造函数的参数和静态工厂方法的参数。
public class ConstructorDI {
DemoBean demoBean = null;
public TestSetterDI (DemoBean demoBean) {
this.demoBean = demoBean;
}
}
复制代码
注解注入只须要在须要在成员变量上添加@Autowire
注解便可
public class ConstructorDI {
@Autowire
private DemoBean demoBean;
}
}
复制代码
组件是一组软件,这些组件将被其它应用程序所使用,且不会进行任何更改。所谓“不更改”是指使用应用程序不会更改组件的源代码,尽管它们能够经过组件做者容许的方式扩展组件来更改组件的行为。
服务与组件类似,供外部应用程序使用。主要的区别在于本地使用的组件(好比jar
文件、程序集、dll
或源导入)。服务将经过同步或异步的某个远程接口(例如,Web
服务,消息系统,RPC
或套接字)远程使用。
依赖项注入器的主要好处是,它容许根据环境和使用状况注入合适的服务实现。注入不是打破这种依赖性的惟一方法,另外一种方法是使用服务定位器。服务定位器的基本思想是拥有一个对象,该对象知道如何掌握应用程序可能须要的全部服务。而后,它将扫描全部此类服务,并将它们存储为单例注册表中。当要求提供服务实现时,请求者可使用令牌查询注册表并获取适当的实现。
一般,这些注册表是经过一些配置文件填充的。关键区别在于,使用服务定位器时,服务的每一个用户都对定位器具备依赖性。定位器能够隐藏对其余实现的依赖关系,可是仍是须要查看定位器。
正如上文已经说过的,关键区别在于,使用服务定位器,服务的每一个用户都对定位器有依赖性。这意味着必须在输入和输出方面了解服务定位器的详细信息。所以,实际上成为选择哪一种模式的决定因素。
若是维护注册表信息既简单又必要,则可使用服务定位器,或者直接使用依赖注入,由于它对服务的使用者是无感知的
基于constructor
的注入,会固定依赖注入的顺序;该方式不容许咱们建立bean
对象之间的循环依赖关系,这种限制实际上是一种利用构造器来注入的益处 - 当你甚至没有注意到使用setter
注入的时候,Spring
能解决循环依赖的问题;
基于setter
的注入,只有当对象是须要被注入的时候它才会帮助咱们注入依赖,而不是在初始化的时候就注入;另外一方面若是你使用基于constructor
注入,CGLIB
不能建立一个代理,迫使你使用基于接口的代理或虚拟的无参数构造函数。
个人偏好是注解注入,这种方式看起来很是好,精短,可读性高,不须要多余的代码,也方便维护;
BeanFactory
就像一个工厂类,其中包含一系列bean
。BeanFactory
在其内部保存多个Bean
的Bean
定义,而后在客户要求时实例化Bean
。
BeanFactory
可以在实例化协做对象之间建立关联。这消除了bean
自己和bean
客户端的配置负担。BeanFactory
还参与bean
的生命周期,从而调用自定义初始化和销毁方法。
Bean
工厂适合简单的应用程序,可是要利用Spring
框架的所有功能,您可能须要升级到Spring
更高级的容器即应用程序上下文。从表面上看,应用程序上下文与Bean
工厂相同,二者都加载Bean
定义,将Bean
绑定在一块儿并根据请求分配Bean
。但它也提供以下功能:
bean
注册监听器的事件。ApplicationContext
的三种经常使用实现是:
ClassPathXmlApplicationContext
:它从位于类路径中的XML
文件中加载上下文定义,并将上下文定义视为类路径资源。使用代码从应用程序的类路径中加载应用程序上下文。ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
复制代码
FileSystemXmlApplicationContext
:它从文件系统中的XML
文件加载上下文定义。使用代码从文件系统中加载应用程序上下文。ApplicationContext context = new FileSystemXmlApplicationContext("bean.xml");
复制代码
XmlWebApplicationContext
:它从Web
应用程序中包含的XML文件中加载上下文定义。BeanFactory
基本上只是实例化和配置Bean
。ApplicationContext
也能够作到这一点,它提供了支持基础设施来支持许多企业特有的特性,例如事务和AOP
。
所以,建议使用ApplicationContext
。
在本教程中,咱们在spring
学习了ioc
和di
之间的区别。
🙂🙂🙂关注微信公众号java干货 不按期分享干货资料