版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
JavaWeb编程技术本章首先介绍Spring框架的基本概念,然后重点介绍Spring的Ioc容器、依赖注入概念和Bean的配置与实例化。Spring框架简介Spring容器的概念依赖注入的概念bean的配置与实例化第9章Spring快速入门Spring是目前最流行的轻量级Java企业开发框架,它是为解决企业应用开发的复杂性而创建的。该框架以强大的功能和卓越的性能受到了众多开发人员的喜爱。Spring框架简介Spring框架1.0版于2004年3月发布。在过去的近20年中,Spring框架一直不断发展,目前已成为Java领域中开发企业应用程序的首选框架。9.1.1Spring框架模块9.1.2添加Spring依赖模块9.1Spring框架模块9.1.1Spring框架是高度模块化的,它包含20多个不同的模块。Spring框架模块提供了Spring反转控制容器、依赖注入(DI)、WebMVC框架、AOP等核心特性。图9-1列出了Spring框架的主要模块。Spring框架模块9.1.1Spring框架的所有模块都用jar文件存储,如果需要特定的技术,可以将它们包含在类路径中。表9-1列出了Spring框架的主要模块,并简要描述了每个模块的内容和用于依赖项管理的构件名称。实际jar文件的名称可能不同,这取决于如何获取模块。模块组描述CoreContainerspring-core和spring-beans模块提供了Spring的DI功能和IoC容器实现。spring-expressions模块为在Spring应用中通过Spring表达式语言配置应用程序对象提供了支持DataAccess/Integrationspring-jdbc模块简化用JDBC与数据库的交互,spring-orm模块提供了与ORM(对象关系映射)框架的集成,如JPA和Hibernate。spring-jms模块简化了与JMS提供者的交互AOP和Instrumentation包含支持AOP(面向切面编程)的类和工具模块。spring-aop模块提供Spring的AOP功能,spring-instrument模块提供了类工具的支持Web/Remotingspring-web和spring-webmvc模块是用于开发Web应用和RESTful的Web服务。spring-webflux为Web应用开发带来了反应式编程能力Test包含spring-test模块,简化了创建单元和集成测试添加Spring依赖模块9.1.2有两种方式使用Spring框架,一种方法是使用Maven构建应用程序,可以在其pom.xml文件中添加所依赖的模块,项目将自动下载Spring框架的模块,如下所示。<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>6.0.2</version></dependency>添加Spring依赖模块9.1.2使用Maven构建工具的一个好处是,下载一个Spring模块,会自动下载它所依赖的模块。比如,若在pom.xml文件中添加了spring-context模块,Maven将自动下载spring-aop、spring-benas、spring-core、spring-jcl和spring-expressions等模块。这几个模块是开发Spring应用的基础。如果需要开发Web应用程序,应该添加spring-webmvc模块,如下所示。<dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>6.0.2</version></dependency>Spring容器与依赖注入9.2Spring容器和依赖注入是Spring框架的两个最基本概念,下面我们介绍这两个概念。9.2.1Spring容器9.2.2依赖注入9.2.3Spring配置文件9.2.4一个简单的Spring程序9.2.5依赖注入实现方式Spring容器9.2.1
任何应用程序都是由很多组件组成的,每个组件负责整个应用功能的一部分,这些组件需要与其他的应用元素进行协调以完成自己的任务。当应用程序运行时,需要以某种方式创建并引入这些组件。Spring的核心是提供了一个容器(container),通常称为应用上下文(applicationcontext),它负责创建和管理应用中所有组件。Spring容器中管理的对象称为bean。Spring容器在启动时通过读取配置文件(applicationContext.xml)中信息构建所有组件对象。容器将这些组件装配到一起,从而形成一个完整的程序。就像一所房子,由砖瓦、木料、水泥等组成一样。Spring容器9.2.1将组件装配在一起,是通过一种基于依赖注入的模式实现的。依赖注入是Spring框架的核心机制,它提供了框架的重要功能,包括依赖注入和bean的生命周期管理功能。图9-2给出了Spring容器中组件管理和依赖注入的示意图。Spring容器9.2.1
要在Spring中实现依赖注入,需要一个容器。在Spring中,它是ApplicationContext接口的一个实例。Spring提供了几种不同的ApplicationContext实现。其中,ClassPathXmlApplicationContext,从类加载路径下的XML文件中获取上下文定义信息。FileSystemXmlApplicationContext,从文件系统的XML文件中获取上下文定义信息。XmlWebApplicationContext,从Web系统中的XML文件中获取上下文定义信息。AnnotationConfigApplicationContext,就需使用Java配置。下面代码创建一个ClassPathXmlApplicationContext容器对象,它从类加载路径下的配置文件中获取上下文信息。StringxmlPath="src/main/webapp//WEB-INF/applicationContext.xml";ApplicationContextcontext=
newClassPathXmlApplicationContext(xmlPath);依赖注入9.2.2
依赖注入是Spring框架的核心特征,其主要目的是降低程序对象之间的耦合度。Java应用程序通常包括多个相互协作对象,这些对象相互依赖。
在传统的程序设计过程中,当某个Java实例(调用者)需要另一个Java实例(被调用者)时,通常由调用者来创建被调用者的实例。
在依赖注入模式下,创建被调用者的工作不再由调用者完成,而是由Spring容器来完成,然后注入给调用者,这称为依赖注入(DependencyInjection,简称DI)。
假设开发一个航班管理应用程序,其中包含Passenger(乘客)和Country(国家)两个实体。每位乘客都来自一个国家,一个Passenger对象就依赖于一个Country对象(见图9-3)。在清单9.1和9.2中直接初始化了这个依赖项。Country.java清单9.1publicclassCountry{ privateStringname; privateStringcodeName; publicCountry(Stringname,StringcodeName){ =name; this.codeName=codeName; } publicStringgetName(){ returnname; } publicStringgetCodeName(){ returncodeName; }}Passenger.java清单9.2publicclassPassenger{privateStringname;privateCountrycountry;publicPassenger(Stringname){=name;this.country=newCountry("中国","CHN");}publicStringgetName(){returnname;}publicCountrygetCountry(){returncountry;}}依赖注入9.2.2
为Passenger类定义了一个name字段和它的getter方法,定义一个country字段和它的getter方法。创建一个构造方法初始化name和country字段。在Passenger的构造方法中,创建并初始化了国家对象,这表明国家和乘客之间存在紧耦合。这种方法的缺点是:Passenger类直接依赖Country类,Passenger类和Country类也不可能分开测试。
正是由于这些缺点,就产生了一个新的方法:依赖注入。使用依赖项注入方法,对象被添加到容器中,容器在创建对象时注入依赖项。这一过程基本上与传统的过程相反,因此也被称为控制反转(inversionofcontrol)。其基本思想是消除应用程序组件对某个实现的依赖,并将类实例化的控制权限委托给容器。对上面示例,要消除对象之间的直接依赖关系,可重写Passenger类,如清单9.3所示。修改后的Passenger.java清单9.3publicclassPassenger{privateStringname;privateCountrycountry;publicPassenger(Stringname){=name;}publicStringgetName(){returnname;}publicCountrygetCountry(){returncountry;}publicvoidsetCountry(Countrycountry){this.country=country;}}Spring配置文件9.2.3Spring从1.0版本开始,就支持基于XML的配置文件,从2.5版本开始,增加了使用注解的配置。下面是Spring的配置文件的基本框架。<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xsi:schemaLocation="/schema/beans/schema/beans/spring-beans-4.3.xsd">…</beans>配置文件的根元素是<beans>,其中可包含其他元素,比如最重要的是使用<bean>元素对容器管理的bean对象进行配置。如果需要更强的Spring配置能力,可以在schemaLocation属性中添加相应的schema。一个简单的Spring程序9.2.4
接下来通过一个示例来演示IoC容器的使用。(1)在IDEA中创建名为chapter09的JakartaEE项目,在pom.xml文件中添加Spring框架所需的依赖项,如下所示。<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency>一个简单的Spring程序9.2.4(2)在src/main/java目录中创建com.boda.xy包,在该包中创建Country类和Passenger类。这里使用清单9.1和清单9.3的类。(3)在src/main/resources目录中创建Spring配置文件applicationContext.xml,配置文件名可以自定义,如清单9.4所示。applicationContext.xml清单9.4<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xsi:schemaLocation="/schema/beans/schema/beans/spring-beans.xsd"><beanid="country"class="com.boda.xy.Country"><constructor-argname="name"value="中国"/><constructor-argname="codeName"value="CHN"/></bean><beanid="passenger"class="com.boda.xy.Passenger"><constructor-argname="name"value="张大海"/><propertyname="country"ref="country"/></bean></beans>FlightSystemTest.java清单9.5publicclassFlightSystemTest{@TestpublicvoidtestPassenger(){StringxmlPath="src/main/webapp//WEB-INF/applicationContext.xml";ApplicationContextcontext=newFileSystemXmlApplicationContext(xmlPath);Passengerpassenger=(Passenger)context.getBean("passenger");System.out.println(passenger.getName());System.out.println(passenger.getCountry().getName());}}(4)在src\test\java中创建com.boda.xy.FlightTest测试类,并在该类中创建一个名为testPassenger()方法,如清单9.5所示。
在测试类的testPassenger()方法中,首先定义了配置文件的路径,然后加载配置文件创建Spring容器,并通过容器获取一个Passenger对象,最后在控制台将它们打印出来。
要在IDEA中运行测试方法,在编辑窗口中单击testPassenger()方法左侧小三角,在弹出菜单中选择RuntestPassenger()命令。使用JUnit测试testPassenger()方法,控制台输出结果如图9-4所示。依赖注入实现方式9.2.5
在Spring中,通过依赖注入的方式调用者只需完成较少的工作。当调用者乘客需要一个国家对象时,可以由Spring容器来创建该国家对象并将其注入到调用对象中。Spring的依赖注入主要有两种方式实现:设值注入。Spring容器使用属性的setter方法来注入被依赖的实例。构造注入。Spring容器使用构造方法来注入被依赖的实例。1.用设值依赖注入
设值依赖注入是指Spring容器通过调用者类的setter方法把所依赖的实例注入。例如在ProductController类中定义一个ProductService类型的成员,然后定义一个setter方法就可以注入ProductService对象。ProductController.java清单9.6publicclassProductController{privateProductServiceproductService;publicProductController(){}//定义setter方法注入一个ProductService实例publicvoidsetProductService(ProductServiceproductService){ductService=productService;}publicintaddProduct(Productproduct){productService.addProduct(product);}}这里,不是在ProductController类的构造方法中创建ProductService实例,而是定义一个setter方法,通过该方法注入一个ProductService实例,而这个实例是由Spring容器创建的。在Spring项目的src/applicationContext.xml配置文件中添加bean的定义,对设值注入的属性使用<property>元素配置,下面文件配置了controller和service两个bean,代码如下。<beanid="service"class="com.boda.service.ProductService"></bean><beanid="controller"class="com.boda.controller.ProductController"><propertyname="productServie"ref="service"></property></bean>这里首先配置了ProductService类的一个bean实例,然后在配置ProductController类的productService属性时,使用了<property>元素的ref属性引用ProductService类的一个实例。ProductService类的bean由service配置。依赖注入实现方式9.2.5
2.用构造方法依赖注入构造方法注入是指Spring容器通过调用者类的构造方法把所依赖的实例注入。基于构造方法的注入需要为调用者类定义带参数的构造方法实现,每个参数代表一个依赖。例如,在ProductController类中可以定义构造方法,如清单9.7所示。ProductController.java清单9.7publicclassProductController{privateProductServiceproductService;//定义构造方法注入ProductService的一个实例publicProductController(ProductServiceproductService){ductService=productService;}publicintaddProduct(Productproduct){productService.addProduct(product);}}这里,为ProductController类定义一个构造方法,将ProductService的一个实例作为构造方法的一个参数注入。在Spring配置文件applicationContext.xml中,对构造注入的属性使用<constructor-arg>元素配置,下面文件配置了ProductController和ProductService两个bean,代码如下。<beanid="service"class="com.boda.service.ProductService"></bean><beanid="controller"class="com.boda.controller.ProductController"><!--为controller对象构造方法注入service对象--><constructor-argref="service"/>
</bean>
设值注入和构造方法注入是目前主流的依赖注入实现方式,这两种方法各有优点,也各有缺点。Spring框架对这两种依赖注入方法都提供了良好的支持,这也为开发人员提供了更多的选择。
那么在使用Spring开发应用程序时应该选择哪一种注入方式呢?
就一般项目开发来说,应该以设值注入为主,辅之以构造方法注入作为补充,可以达到最佳的开发效率。bean的配置与实例化9.3可以把Spring容器看做是一个用于生产和管理bean大型工厂。要使用这个工厂生产和管理bean,需要开发者在配置文件中配置bean。Spring容器一般使用XML配置文件注册并管理bean之间的依赖关系。XML配置文件的根元素是<beans>,其中包含多个<bean>子元素,每个<bean>子元素定义一个bean,并描述该bean如何被装配到Spring容器中。<bean>元素可包含多个属性和一些子元素,具体如表9-2所示。构造方法初始化9.3.1Spring容器可以调用bean类的无参数或有参数构造方法实例化bean,这种方式称为构造方法实例化。下面代码就是调用ProductService类的无参数构造方法创建bean实例。<beanid="service"class="com.boda.service.ProductService"></bean>向构造方法传递参数9.3.2Spring支持通过带参数的构造方法初始化类。假设Employee类定义了如下构造方法:下面的bean定义使用<constructor-arg>子元素通过参数名指定传递给构造方法的参数值。publicEmployee(Stringname,intage){=name;this.age=age;}<beanid="employee"class="com.boda.xy.Employee"><constructor-argname="name"value="张大海"/><constructor-argname="age"value="20"/></bean>除通过名称传递参数外,Spring还支持通过索引的方式传递参数,第一个参数的索引值为0,第二个参数索引值为1,以此类推。具体如下。<beanid="employee"class="org.bu.xxxy.Employee"><constructor-argindex="0"value="张大海"/><constructor-argindex="1"value="20"/></bean>需要说明的是,采用这种方式,必须传递对应构造方法的所有参数,缺一不可。静态工厂实例化9.3.3Spring还支持通过调用类的一个工厂方法来初始化类。下面代码创建一个工厂类RobotFactory,该类中定义一个静态方法createRobot()用来实例化Robot对象,代码如下。在配置文件applicationContext.xml文件中添加配置代码。下面的bean定义展示了通过工厂方法来实例化com.boda.xy.Robot。publicclassRobotFactory{publicstaticRobotcreateRobot(){returnnewRobot("教师机器人");}}<beanname="robot"class="com.boda.RobotFactory"
factory-method="createRobot"/>使用下面代码返回配置的Robot实例。StringxmlPath="applicationContext.xml";ApplicationContextcontext=newClassPathXmlApplicationContext(xmlPath);Robotrobot=(Robot)context.getBean("robot");System.out.println(robot.getName());实例工厂实例化9.3.4在使用实例工厂实例化bean时,要求在开发者在工厂类中创建一个实例方法来创建bean的实例。在配置bean时需要使用factory-bean属性指定配置的工厂,同时还需要使用factory-method属性指定实例工厂中的实例方法。下面创建一个工厂类RobotFactory,该类中定义一个实例方法createRobot()用来实例化Robot对象,代码如下。publicclassRobotFactory{publicRobotcreateRobot(){returnnewRobot("教师机器人");;}}实例工厂实例化9.3.4在applicationContext.xml配置文件中添加配置代码。下面的bean定义展示了通过实例工厂方法来实例化com.boda.Robot。该例中使用facory-bean属性指定实例工厂,使用facory-method属性指定实例方法。下面是测试代码:<beanname="robotFactory"class="com.boda.RobotFactory"/><beanname="robot"factory-bean="robotFactory"factory-method="createRobot"/>StringxmlPath="applicationContext.xml";ApplicationContextcontext=newClassPathXmlApplicationContext(xmlPath);Robotrobot=(Robot)context.getBean("robot");System.out.println(robot.getName());销毁方法的使用9.3.5有时,希望类在销毁之前执行某些操作,这可以在bean定义中使用destroy-method属性,来指定在bean销毁前要被执行的方法。下例bean定义通过java.util.concurrent.Executors的newCachedThreadPool()静态方法创建一个java.util.concurrent.ExecutorService实例,通过destroy-method属性指定销毁方法shutdown()。这样,Spring会在销毁ExecutorService实例前,调用其shutdown()方法。<beanid="executorService"class="java.util.concurrent.Executors"factory-method="newCachedThreadPool"
destroy-method="shutdown"/>bean的装配方式9.4bean的装配可以理解为如何在Spring容器中创建bean及注入依赖关系,bean的装配方式即bean依赖注入的方式。Spring容器支持多种形式的装配方式,包括基于XML的装配、基于注解的装配和基于Java代码的装配。9.4.1基于XML的装配9.4.2基于注解的装配基于XML的装配9.4.1
基于XML的装配是指在Spring的配置文件中声明bean以及依赖注入。9.2节中介绍的依赖注入就是属于这种方式。
使用XML配置文件有两种依赖注入方式:构造注入和设值注入。使用设值注入时,在Spring的配置文件中,需要使用<bean>元素的<property>子元素为每个子元素注入值。设值注入要求bean类必须满足以下两点要求:bean类必须提供一个默认的构造方法。bean类必须为需要注入的属性提供对应的setter方法。对于使用构造注入时,在Spring的配置文件中,需要使用<bean>元素的<constructor-arg>子元素类定义构造方法的参数,可以使用其value属性或子元素设置参数值。构造注入要求bean类必须提供带参数的构造
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 二零二四年度城市规划策划咨询合同
- 少儿美术合同范本
- 2024年度工程分包详细具体标的合同
- 采购锅炉合同范本
- 2024年仓储合同例子
- 2024年度保温材料生产线设备购销合同
- 2024年度果园废弃物资源化利用合同
- 重工施工合同范本
- 城墙修葺合同范本
- 二零二四年度门卫服务外包合同
- 班会-学霸的炼成
- 临安遗恨-古筝+钢琴五线谱
- 抽象代数复习习题及答案
- 薪酬管理分析报告5篇
- 台海局势之我见课件
- 药学类之药学(中级)题库大全包过题库及参考答案
- 中医师承拜师合同公证书(通用)
- 2019年上海闵行区初三英语二模卷(高清版-附听力文稿、答案)
- 解剖学 第七章 生殖系统课件
- 科室高风险患者管理记录登记表
- 《大学生劳动教育》第七章 合作性劳动与集体劳动
评论
0/150
提交评论