了解依赖注入和控制反转的概念,然后借助代码示例了解Spring框架如何支持它们。控制反转在我们开始做任何事情之前,让我们了解一下什么是控制反转。控制反转是面向对象编程中使用的一个术语,通过该术语,将一个对象或一组对象的控制权交给框架或框架提供的容器。上图虽然很幽默,但是描述了什么是InversionofControl。如果我们将人类视为软件组件或服务,那么他们的目的就是执行起床、参加会议或支付账单等动作。对于其他事情,例如跟踪会议、设置闹钟或提醒人们使用他们的手机或任何智能设备。什么是依赖?一个应用程序由多个类组成。通常,每个类都应该有自己的专门职责。这导致我们的类与不同的类集成以完成某些功能。当A类调用B类的方法时,A类依赖于B类。紧耦合对象了解依赖性如何导致紧耦合对象出现问题。请参阅下面的代码。这是一个FileUploadService,它获取文件,检查文件是否具有预期的扩展名之一,并请求FileStorageService存储文件。公共类FileUploadService{privateListvalidFiles=Arrays.asList("xls","doc"."txt","ppt");私有FileStorageService服务=新AzureBlobStorageService();公共文件上传服务(){}//</font>//其他方法//}在上面的代码中,我们使用ProgramtoInterface的原理来实例化文件存储服务。但是,相应的实现仍然硬编码在类中,validFiles也是硬编码的。它们都导致紧密耦合的对象。松散耦合的对象让我们稍微更新一下FileUploadService,我们将获得松散耦合的对象。公共类FileUploadService{privateListvalidFiles;privateFileStorageService服务;publicFileUploadService(ListvalidFiles,FileStorageService服务){this.validFiles=validFiles;this.service=service;}classUser{publicstaticvoidmain(String[]ar){ListvalidFiles=Arrays.asList("xls","ppt","doc");FileStorageServiceservice=newAzureBlobStorageService();FileUploadServicefileUploadService=newFileUploadService(validFiles,service);}第3行:变量已声明但未初始化且没有硬编码值。第4行:仅引用FileStorageService类型。没有额外的实现。第6行:全参数构造函数。让我们看看User类中发生了什么,它实际上是FileUploadService。第17行:FileUploadService通过将所有必需的参数传递给构造函数来创建一个实例。依赖注入我们刚才所做的称为依赖注入。依赖注入是面向对象编程中使用的一个术语,通过该术语对象将专注于执行分配的功能并利用其他对象。对象不会处理必要的配置和初始化。但是,对象将提供一种方法来通过字段赋值、字段设置器或构造函数来初始化它们及其依赖项。这样,外部实体可以初始化事物而不是实际对象。在基于Spring的应用程序中,控制反转容器(IoC容器)执行依赖注入。我们将在下一节中看到这一点。首先,让我们看看为什么我们甚至需要这样一个容器。为什么我们需要IoC容器?我修改了之前的代码示例。它现在是一个ResumeUploaderService。候选人可以将其简历分享到ResumeUploaderService。该服务应在验证扩展后将其共享给ResumeStorageService。根据组织当前的政策,简历存储在文件系统的机密文件夹中(由publicclassResumeUploaderService{privateListvalidFiles;/font>privateResumeStorageService服务;publicResumeUploaderService(ListvalidFiles,ResumeStorageServiceservice){this.validFiles=validFiles;/font>this.service=service;classCandidate{publicstaticvoidmain(String[]ar){ListvalidFiles=Arrays.asList("pdf","doc");<字体>字体>StringfilePath="/Users/app/confidential/storage/resume";ResumeStorageServiceservice=newFileSystemResumeStorageService(filePath);ResumeUploaderServicefileUploadService=newResumeUploaderService(validFiles,service);第4行:ResumeUploaderService引用了ResumeStorageService。第6行:接受并设置ResumeStorageService。要上传Resume,Candidate必须实例化ResumeUploaderService并传递resume,但是由于所有这些依赖注入,Candidate的工作变得很困难。考生不仅要实例化ResumeUploaderService,还要实例化ResumeStorageService。因为,没有后者,就无法实例化前者。第17行:候选人决定在哪里存储简历(我知道……这很有趣!!)第18行:候选人决定是使用FileSystemResumeStorageService还是AzureBlobStorageService。第20行:最后,候选人实例化ResumeUploaderService。以下是消费者太了解的上述重要问题。消费者不是使用该服务,而是对其进行初始化。消费者不应该担心ResumeUploaderService如何完成它的工作(缺乏抽象)。作为最终的消费者,我们必须知道一切,我们必须初始化系统中的一切。这清楚地表明我们需要处理所有配置和初始化的东西。唯一负责管理初始化的东西。InversionofControlContainer(IoCContainer)Spring提供了一个IoCContainer来解决这个问题。该容器实例化所有对象,并解析它们的依赖关系。类ApplicationContext表示SpringIOC容器。应用程序上下文负责实例化、配置和连接bean。请记住,bean只不过是在Spring的应用程序上下文中注册的Java对象。要配置、实例化或编写bean,应用程序上下文需要一些指令。这些指令可以作为XML配置、Java注释或代码提供。Spring依赖注入在Spring中,每个对象都是一个bean。每个对象都有一个ID或名称。ApplicationContext跟踪所有这些bes和id。当消费者请求一个bean时,应用程序上下文返回一个bean实例。查看下面的代码以了解有关bean创建和连接的更多信息。importorg.springframework.beans.factory.annotation.Value;importorg.springframework.stereotype.Component;@Component("resumeStorageService")公共类FileSystemResumeStorageService实现ResumeStorageService{@Value("${resume.storage.path}")privateString存储路径;//根据属性文件分配存储路径////跳过方法//}第4行:告诉Spring将此类注册为bean并通过给定的名称对其进行标识。如果未提供名称,则将类名视为标识符。第8行:存储路径现在直接从属性文件中注入。消费者不需要通过它。importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.beans.factory.annotation.Qualifier;importorg.springframework.stereotype.Component;@ComponentpublicclassResumeUploaderService{@Autowired@Qualifier("resumeStorageService")privateResumeStorageServicestorageService;publicResumeUploaderService(ResumeStorageServicestorageService){/font>this.storageService=storageService;}////跳过的方法//<字体>字体>}第5行:将类声明为SpringBean,并将类名声明为标识符第10行:通过“resumeStorageService”告诉spring自动连接ResumeStorageService。如果我们想附加一个不同的实现,ResumeStorageService那么ResumeUploaderService根本不会改变。导入org.springframework.beans.factory.annotation.Autowired;publicclassCandidate{@AutowiredprivateResumeUploaderServiceresumeUploaderService;>publicvoidupload(Byte[]resume){resumeUploaderService.uploadResume(resume);}第4行:要求Spring分配resumeUploaderService。一切都是那么干净和专注。没有类正在初始化另一个类或为另一个类设置任何配置。一切都由Spring的控制反转容器(IoC容器)管理。总结您已经完成了Spring依赖注入和控制反转指南。您了解了什么是依赖关系以及类如何紧密耦合或松散耦合。我们了解了面向对象编程中依赖注入和控制反转的概念。您还了解到Spring的控制反转容器(IoC容器)管理我们Spring应用程序中的所有依赖项注入。