你不知道系列--Spring IOC的秘密

什么是IOC控制翻转?

Spring作为常用框架,面试的时候经常会有面试官问,Spring IOC了解吗?作为面试者回答:这个我知道,Spring IOC控制翻转,就是把实例化的对象交给Spring容器来实始化。 面试官继续问:哪里说说IOC控制翻转有什么作用(优点),是怎么实现的?作为面试者:enmmmm…这个时候就很尴尬了。

任何事情不能局限于表面,需要有求知意识,尽自己能力和理解去探求真相,当然这个也不是一蹴而就,是一个循序渐进的过程,重要的是在这条路上需要不断求索。

了解Bean是如何在Spring中配置的

Bean默认是配置在applicationContext.xml文件中,那么我们首先需要明白Spring是如何加载配置文件的,请看博文:你不知道系列–Spring是如何加载配置文件

通过博文我们会了解到Spring配置文件是如何实现加载的,Spring配置文件实例化的流程,通过依赖Servlet的创建和销毁,来实现Soring配置文件加载和销毁,其实ContextLoaderListener是web组件,真正实例化的是Tomcat,Tomcat在启动加载web.xml实例化并识别Lintenter配置,Spirng是维护了ApplicationContext对象(容器对象),通过ApplicationContext对象读取配置文件。

了解Bean是如何在Spring中实例化

在了解Spring如何加载配置文件和读取Bean后,那么Bean是如何进行实例化的,以及Bean的生命周期流程是什么,请看博文:spring–Bean生命周期。

通过博文我们会了解到通过Spring维护的applicationContext对象(容器对象),可以通过getBean()来获取指定Bean对象,是不是很神奇?,不仅如此,如果知道Bean的生命周期,我们还能再Bean实例化的各个步骤中进行动态处理。

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
}

容器对象ApplicationContext

ApplicationContext接口继承了很多接口,这些接口我们可以将其分为五类:

  • MessageSource,主要用于国际化
  • ApplicationEventPublisher,提供了事件发布功能
  • EnvironmentCapable,可以获取容器当前运行的环境
  • ResourceLoader,主要用于加载资源文件
  • BeanFactory,负责配置、创建、管理Bean,IOC功能的实现主要就依赖于该接口子类实现。

具体的接口功能,大家有兴趣可以了解,推荐博文:https://blog.csdn.net/qq_41907991/article/details/104890350

应该如何理解Spring核心思想IOC控制翻转:

对象的创建交给外部容器完成,这个就做控制反转。

  • Spring使用控制反转来实现对象不用在程序中写死
  • 控制反转解决对象处理问题【把对象交给别人创建】

如何理解DI,是如何处理对象之间的依赖问题:

  • Spring使用依赖注入来实现对象之间的依赖关系
  • 在创建完对象之后,对象的关系处理就是依赖注入

IOC和DI关系

IoC 全称为 Inversion of Control,翻译为 “控制反转”,它还有一个别名为 DI(Dependency Injection),即依赖注入。
DI—Dependency Injection,即“依赖注入”:是组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。

理解DI依赖注入

扫描二维码关注公众号,回复: 11586698 查看本文章
  • Spring使用依赖注入来实现对象之间的依赖关系(实际开发中我们常用的@Autowired注解标注在对象属性上,实际就是提供了对象属性的Set方法)
  • 在创建完对象之后,对象的关系处理就是依赖注入

Srping如何处理Bean的属性注入

  • 有参构造注入
  • set方法注入

总结:
所谓 IOC ,就是由 Spring IOC 容器来负责对象的生命周期和对象之间的关系。

来段代码看看没有IOC容器进行属性注入

  • 定义一个水果类接口
public interface Fruit {

	public void get();

}
  • 实现水果的类,具体水果
public class Apple implements Fruit {

	public void get() {
		// TODO Auto-generated method stub
		System.out.println("拿到苹果!!!");
	}

}



public class Banana implements Fruit {

	public void get() {
		// TODO Auto-generated method stub
		System.out.println("拿到香蕉!!");
	}

}
  • Service业务层,这里主要是体现业务逻辑
    (体现组件之间的依赖关系,对象属性的注入)
public class UserService {

	private Fruit fruit = new Apple();

	public void getName() {
		fruit.get();
	}
}
  • 模拟用户类调用
public class User {

	public static void main(String[] args) {
		UserService us = new UserService();
		us.getName();
	}

}

思考:

其实这一段代码没什么问题,控制会输出"拿到苹果!!",这也符合我们代码需求,但是水果的实现不止一种,如果我们需要香蕉呢?这个时候就需要改动Service代码,把苹果换成香蕉,那么每次更换都需要重新new水果对象,这样一点都不灵活,其实我们需要思考一个问题?我们每次用到自己依赖的对象真的需要自己去创建吗?我们知道,我们在UserService依赖的Fruit对象其实并不是依赖该对象本身,而是依赖它所提供的服务(不同水果对象,提供不同的水果),只要在我们需要它的时候,它能够及时提供服务即可,至于它是我们主动去创建的还是别人送给我们的,其实并不是那么重要。再说了,相比于自己千辛万苦去创建它还要负责初始化、管理使用、销毁等方法而言,直接有人送过来是不是显得更加好呢?
IOC就是给我们送东西过来的人,或者理解称为中介,需要什么直接找到IOC容器,用户需要苹果,并不需要直接创建苹果,而是开放程序接口,由IOC容器进行注入。
IOC的思想最核心的地方在于,资源不由使用资源的双方管理,而由不使用资源的第三方管理,这可以带来很多好处。第一,资源集中管理,实现资源的可配置和易管理。第二,降低了使用资源双方的依赖程度,也就是我们说的耦合度。

再来段代码看看IOC容器,通过set属性注入后的变化

  • 在Service业务层依赖水果类,我们给水果类提供了Set方法进行属性注入
public class UserService {

	private Fruit fruit;

	public void getName() {
		fruit.get();
	}
	public void setFruit(Fruit fruit) {
		this.fruit = fruit;
	}

}
  • 模拟用户调用,这时我们需要什么水果权限,就给到用户来决定(控制权限翻转)。
public class User {

	public static void main(String[] args) {
		UserService us = new UserService();
		us.setFruit(new Banana());
		us.getName();
	}

}

最后总结一下使用IOC的好处:

  • 不用自己组装,拿来就用。
  • 享受单例的好处,效率高,不浪费空间。
  • 便于单元测试,方便切换mock组件。
  • 便于进行AOP操作,对于使用者是透明的。
  • 统一配置,便于修改。
    Spring IOC容器和DI(依赖注入的)是相辅相成的关系,通过组件或对象的注入实现对象创建,不需要用户亲自管理组件或对象的组合装配,这些都交给IOC容器进行管理,需要什么从资源管理的第三方IOC容器获取,用户只需要专注自己的业务逻辑。

希望帮助大家更熟悉Spring IOC的原理和意义,请多多支持我的博客!

猜你喜欢

转载自blog.csdn.net/qq_41714882/article/details/105055483