当前位置: 首页 > 后端技术 > Java

SpringIoC的基本概念

时间:2023-04-01 15:41:58 Java

Java开发中SSM框架集成开发中的SpringIoCInversionofControl(IoC)是一个比较抽象的概念,它是Spring框架的核心,用来降低系统的耦合问题电脑程序。依赖注入(DependencyInjection,DI)是IoC的另一个术语,但它从不同的角度描述了同一个概念。比如我们想吃面包:以前我们要买面粉自己做。但是现在有实体店或者网店,你可以告诉店家你想要的口味,让店家来做。这时候的面包不是我们自己做的,而是店家做的,不过这个面包完全符合我们的口味。这个例子很形象地说明了控制反转的思想,就是把做面包的主动权交给店主。当一个Java对象(调用者,如你)需要调用另一个Java对象(被调用者,即依赖对象,如面包)时,在传统的编程模式下,调用者通常采用“newcallee”的代码方式创建对象(如制作自己的面包)。这种方式会增加调用者和被调用者之间的耦合度,不利于后期代码的升级和维护。当Spring框架出现后,对象的实例不再由调用者创建,而是由Spring容器(如面包店)创建。Spring容器会负责控制程序之间的关系(比如面包店负责控制你和面包的关系),而不是由调用者的程序代码直接控制。这样,控制权就从调用者转移到了Spring容器中,控制权被反转,也就是Spring的控制反转。从Spring容器的角度来看,Spring容器负责将依赖对象赋值给调用者的成员变量,相当于为调用者注入了自己所依赖的实例。这就是Spring的依赖注入。控制反转是一种通过描述(在Spring中可以是XML或注解)并通过第三方生成或获取特定对象的方式。Spring中实现控制反转的是IoC容器,其实现方式是依赖注入。如果不太明白,也可以看看这个解释:IOC(InversionofControl):全称:InverseofControl。从字面上看,就是inversionofcontrol,将一个内置对象的控制权反转到它自己的对象中。反转之后,自己的对象将不再控制这个内置对象的创建,而是第三方系统。控制此内置对象的创建。DI(DependencyInjection):全称是DependencyInjection,意思是通过注入创建自己对象中的内置对象。那么IOC和DI是什么关系呢?IOC是一种软件设计思想,DI是这种软件设计思想的一种实现。Spring中的核心机制是DI。SpringIoC容器SpringIoC容器的设计主要基于BeanFactory和ApplicationContext这两个接口。1、BeanFactoryBeanFactory提供完善的IOC服务支持。它是一个管理bean的工厂,主要负责初始化各种bean。(Bean相关知识将在下一章介绍)创建BeanFactory实例时,需要提供XML文件的绝对路径。例如第一章ch1应用中main方法的代码可以修改如下://初始化Spring容器,加载配置文件BeanFactorybeanFac=newXmlBeanFactory(newFileSystemResource("D:\eclipse-workspace\ch1\src\applicationContext.xml"));//通过容器TestDao获取测试实例tt=(TestDao)beanFac.getBean("test");tt.sayHello();使用BeanFactory实例来加载Spring配置文件在实际开发中并不多见,我们理解下面就可以了。2、ApplicationContextApplicationContext是BeanFactory的一个子接口,也叫应用上下文。除了包括BeanFactory的所有功能外,它还增加了对国际化、资源化和事件传播的支持。创建ApplicationContext接口的实例通常有3种方式:1、通过ClassPathXmlApplicationContext创建ClassPathXmlApplicationContext会从类路径classPath目录(src根目录)中搜索指定的XML配置文件,例如:ApplicationContextappCon=newClassPathXmlApplicationContext("applicationContext.xml");2。通过FileSystemXmlApplicationContext创建FileSystemXmlApplicationContext会从指定文件的绝对路径中搜索XML配置文件(不常用),找到并加载ApplicationContext的实例化。例如:ApplicationContextappCon=newFileSystemXmlApplicationContext("D:\eclipse-workspace\ch1\src\applicationContext.xml");3。通过Web服务器实例化ApplicationContext容器。Web服务器实例化ApplicationContext容器时,一般采用基于org.springframework.web.context.ContextLoaderListener的实现方式(需要将spring-web-5.0.2.RELEASE.jar复制到WEB-INF/lib目录下),该方法只需要在web.xml中添加如下代码:contextConfigLocationclasspath:applicationContext.xmlorg.springframework.web。context.ContextLoaderListener依赖注入的类型Spring中实现IoC容器的方法就是依赖注入。依赖注入的作用是在使用Spring框架时动态创建它所依赖的对象(如属性值)注入到Bean组件中。Spring框架中依赖注入通常有两种实现方式:一种是构造函数注入,一种是属性setter方法注入。1、构造方法注入Spring框架可以利用Java的反射机制,通过构造方法完成依赖注入。Java反射相关知识文章:浅谈Java的反射机制。在ch2应用中,创建一个dao包,在包中创建一个TestDIDao接口和一个接口实现类TestDIDaoImpl。创建dao的目的是在服务中使用构造函数依赖注入TestDIDao接口对象。packagedao;importorg.springframework.stereotype.Service;@ServicepublicclassTestDIDaoImplimplementsTestDIDao{@OverridepublicvoidsayHello(){System.out.println("TestDIDaosay:Hello,Studyhard!");}}packagedao;publicinterfaceTestDIDao{publicvoidsayHello();}在ch2应用中,创建一个服务包,并在这个包中创建一个TestDIService接口和一个接口实现类TestDIServiceImpl。使用TestDIServiceImpl中的constructor方法注入TestDIDao接口对象。包服务;导入dao.TestDIDao;公共类TestDIServiceImpl实现TestDIService{privateTestDIDaotestDIDao;//依赖注入的构造方法publicTestDIServiceImpl(TestDIDaotestDIDao){super();this.testDIDao=testDIDao;}@OverridepublicvoidsayHello(){//调用testDIDao中的sayHello方法testDIDao.sayHello();System.out.println("TestDIServiceconstructorinjectionsay:Hello,Studyhard!");}}在src根目录下创建一个Spring配置文件applicationContext.xml。在配置文件中,首先将dao.TestDIDaoImpl类托管给Spring,让Spring创建它的对象。其次,将service.TestDIServiceImpl类托管给Spring,让Spring创建它的对象,并将实参传递给构造方法。<属性名="testDIDao"ref="myTestDIDao"/>在ch2应用中,创建一个测试包,并在这个包中创建一个测试类TestDI。具体代码如下:packagetest;importorg.springframework.context.ApplicationContext;importorg.springframework.context.support.ClassPathXmlApplicationContext;importservice.TestDIService;publicclassTestDI{publicstaticvoidmain(String[]args){//初始化Spring容器ApplicationContext,加载配置文件ApplicationContextappCon=newClassPathXmlApplicationContext("applicationContext.xml");//通过容器获取testDIService实例,将测试构造函数注入TestDIServicets=(TestDIService)appCon.getBean("testDIService");ts.sayHello();//通过容器获取testDIService实例,测试setter方法注入TestDIServicets1=(TestDIService)appCon.getBean("testDIService1");ts1.sayHello();}}2.属性setter方法注入Setter方法注入是最主流的注入Spring框架中的方法。它使用JavaBean规范定义的setter方法来完成注入,具有灵活性和可读性。setter方法注入也是Spring框架利用Java反射机制实现的。在服务包中创建接口实现类TestDIServiceImpl1,并使用TestDIServiceImpl1中的属性setter方法将TestDIDao接口对象注入依赖。包服务;导入dao.TestDIDao;公共类TestDIServiceImpl1实现TestDIService{privateTestDIDaotestDIDao;//添加testDIDao属性的setter方法进行依赖注入publicvoidsetTestDIDao(TestDIDaotestDIDao){this.testDIDao=testDIDao;}@OverridepublicvoidsayHello(){//调用testDIDao中的sayHello方法testDIDao.sayHello();System.out.println("TestDIServicesettermethodinjectionsay:Hello,Studyhard!");}}将service.TestDIServiceImpl1类托管给Spring,让Spring创建它的对象。同时调用TestDIServiceImpl1类的setter方法完成依赖注入。在配置文件中添加如下代码:在主类中,添加如下代码测试setter方法注入://获取通过容器测试testDIService实例并通过setter方法注入TestDIServicets1=(TestDIService)appCon.getBean("testDIService1");ts1.sayHello();最后测试截图:总结1为什么使用Spring:使用Spring框架是主要是为了简化Java开发(大部分框架都是为了简化开发),它为我们封装了很多完善的功能,Spring的生态系统也非常庞大。基于XML的配置是Spring提供的最原始的依赖注入配置方式。自Spring诞生以来就已经面世,功能也是最全的(不过好像还有更好的配置方式,明天见!)。2、为什么要使用依赖注入:在传统代码中,每个对象负责管理自己所依赖的对象,所以如果需要切换依赖对象的实现类,需要修改多个地方。同时,过度的耦合也使得对象难以进行单元测试。依赖注入将对象的创建交给外部管理,解决了代码的紧耦合问题,是一种代码实现松耦合的机制。松耦合使代码更加灵活,更好地响应需求的变化,也便于单元测试。