控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)
粗俗的讲,Spring-IOC的出现就是为了解决项目中耦合度过高的问题,将对象的生命周期(创建到销毁)以及使用交给IOC容器进行统一管理。
IOC和DI的关系?IOC更像是一种目标,DI是实现。 IOC是解决耦合度过高的思想,DI(依赖注入) 是实现这种思想的一种 解决方式。
关系图:
除了DI(依赖注入)这种实现方式,还有一种方式是DL(依赖查找),那么依赖注入和依赖查找是什么? 如下
//依赖查找
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/application-context.xml");
MyBean bean = applicationContext.getBean("myBean")
//依赖注入
@Component
public class MyClass{
@AutoWire
MyBean myBean;
比如A.class中有一个B.class的属性,那么我们可以理解为A依赖了B。
public class A{
//在类A中使用了类B
public B b=new B();
public void test(){
System.out.println(b.getSys());
}
}
IOC的设计思想源自如面向对象六大基本原则之一 依赖倒置原则
a.高层模块不应该依赖于底层模块,两者应该依赖于其抽象。
b.抽象不应该依赖具体实现,具体实现应该依赖抽象。
这样的设计初衷也正是为了高内聚,低耦合,因为我们得项目,是需要频繁进行更新的,耦合为大大提高更新项目的难度。
spring实现IOC的思路是提供一些配置信息用来描述类之间的依赖关系,然后由容器去解析这些配置信息,继而维护好对象之间的依赖关系,前提是对象之间的依赖关系必须在类中定义好
SpringIOC实现的过程
a.应用程序中提供类,提供依赖关系(属性或者构造方法)
b.把需要交给容器管理的对象通过配置信息告诉容器(xml、annotation,javaconfig)
c.把各个类之间的依赖关系通过配置信息告诉容器
d.容器负责创建(反射机制),并且负责进行注入与控制事务(单例等)
在我们日常开发中,依赖关系较多而且随着项目逐渐的依赖关系复杂,如果只依靠我们在xml文件进行Property,那么会造成配置文件的臃肿。这对开发人员是非常苦恼的,在Spring中,为我们提供了依赖关系的自动注入,我们查看Spring开发手册可以发现注入的方式有4种。
No自然是不会进行自动装配,重点介绍在开发常用的两种byName,byType。
byName:由属性名自动装配
将它的属性与在配置文件中被定义为相同名称的 beans 的属性进行连接。
<!-- setter注入 -->
<bean id="person" class="com.sheng.Person">
<property name="age" value="18"/>
<property name="name" value="二蛋"/>
</bean>
<!--byName 根据属性名自动装配 autowire配置自动注入的类型-->
<bean id="man" class="com.sheng.Man" autowire="byName"></bean>
byType:由属性数据类型自动装配
<!--byType 根据属性名自动装配 -->
<bean id="man" class="com.sheng.Man" autowire="byType"></bean>
切记:如果在自动注入的时候,byType可能出现多个相同类型的,此时就会报错,因为IOC容器无法确定使用哪个。
除了XML配置外,常见的还有@Autowired与@Resource,Annotation这种配置方式
两者最大的区别,在于@Autowired的默认优先是byType装配,而@Resource是优先类命匹配,也就是byName。
BeanFactory:是Spring里面最底层的接口,包含了各种Bean的定义,读取bean配置文档,管理bean的加载、实例化,控制bean的生命周期,维护bean之间的依赖关系。
ApplicationContext: 接口作为BeanFactory的派生,除了提供BeanFactory所具有的功能外,还提供了更完整的框架功能
区别简单的来说:BeanFactory相当于是一个对使用者开放的功能调用接口,而ApplicationContext更像是一个对于开发者开放的接口。
在Spring开发手册种,给出了6种作用域:
在开发种常见的作用域解释如下:
Spring开发文档中特别提到的问题,意思是在Singleton 当中引用了一个Prototype的bean的时候会引发当前Bean的多例模式的失效
参考https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-factory-method-injection
在Spring中提供了回调方法,回调方法,简介的概括来说,形似于JAVA API提供的finally,即Bean的创建和销毁前后都可以使用回调方法进行后续处理。
@Repository
public class TestClass implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("当前所在类当被IOC容器创建后,此方法将会执行");
}
}
@Repository
public class TestClass implements DisposableBean {
//Bean实例销毁后的回调函数
@Override
public void destroy() throws Exception {
System.out.println("在IOC容器销毁造成此类Bean实例销毁后,会执行此回调函数");
}
}