java 的春天
在21世纪初出现的基于组件的框架中,Spring也许是最好的。 它极大地改善了开发人员在基于Java的应用程序中编写和交付基础结构代码的方式。 自成立以来,Spring被公认为企业Java开发的领先框架。 作为端到端的应用程序框架,Spring反映了Java EE的某些功能,但是它提供了功能和编程约定的组合,这些在其他地方是找不到的。
本文介绍了Spring及其核心编程哲学和方法:控制反转和依赖注入。 您还将开始使用Spring注释和一些动手的编码示例。
依赖注入和控制反转
Spring的核心思想是,您不必自己管理对象关系,而是将它们卸载到框架中。 控制反转(IOC)是用于管理对象关系的方法。 依赖注入是实现IOC的机制。 由于这两个概念相关但不同,因此让我们更仔细地考虑它们:
- 控制反转 (IOC)的作用恰如其名:将传统的控制层次结构反转以实现对象关系。 关系不是由应用程序代码定义对象之间如何关联的,而是由框架定义的。 作为一种方法,IOC为对象关系引入了一致性和可预测性,但是它确实要求您(作为开发人员)放弃一些细粒度的控制。
- 依赖项注入 (DI)是一种机制,框架可以将依赖项“注入”到您的应用程序中。 这是IOC的实际实施。 从某种意义上说,依赖注入取决于多态性 ,它允许引用类型的实现根据框架中的配置而改变。 该框架注入变量引用,而不是在应用程序代码中手动实现它们。
JSR-330
像Java世界中的许多地方一样,Spring作为一种狂野的创新而开始,在某种程度上已经被标准规范所吸收。 在这种情况下,JSR-330是Java标准。 关于JSR-330规范的好处是,您可以在其他地方使用它,并将在Spring之外的其他地方看到它的使用。 您可以不使用Spring而使用它。 但是,Spring给桌面带来了更多的好处。
例子1:Spring依赖注入
通过使用它们可以最好地理解控制反转和依赖注入,因此我们将以一个快速的编程示例开始。
假设您正在为汽车建模。 如果使用普通的旧Java建模,那么Car
类上可能有一个接口成员来引用Engine
接口,如清单1所示。
清单1.普通的旧Java中的对象关系
public Interface Engine() { ... }
public class Car {
private Engine engine;
public Engine getEngine() { ... }
public void setEngine(Engine engine) { ... }
}
清单1包含一个Engine
类型的接口,以及一个具体的Car
类型的类,该类引用了Engine
。 (请注意,在实际的编程场景中,这些文件将放在单独的文件中。)现在,当您创建Car
实例时,您将设置关联,如清单2所示。
清单2.使用Engine界面创建汽车
// ...
Car newCar = new Car();
Engine sixCylEngine = new InlineSixCylinderEngine();
newCar.setEngine(sixCylEngine );
// Do stuff with the car
请注意,您首先创建了Car
对象。 然后,您创建一个满足Engine
接口的新对象,并将其手动分配给Car
对象。 这就是对象关联在普通的旧Java中的工作方式。
在Spring中建模类和对象
现在让我们看一下Spring中的相同示例。 在这里,您可以执行清单3中所示的操作。从Car
类开始,但是在这种情况下,向它添加一个注释: @Inject
。
清单3.在Spring中使用@Inject批注的示例
public class Car {
@Inject
private Engine engine;
// ...
}
使用@Inject
批注(或使用@Autowired
,如果您愿意的话)告诉Spring根据一组规则搜索上下文并将对象自动注入到引用中。
接下来,考虑@Component
批注,如清单4所示。
清单4. @Component批注
@Component
public class InlineSixCylinderEngine implements Engine{
//...
}
用@Component
注释一个类告诉Spring它可用于完成注入。 在这种情况下,将InlineSixCylEngine
,因为它可用并且满足关联的接口要求。 在Spring,这称为“自动接线”注射。 (有关Spring的@Autowired
注释的更多信息,请参见下文。)
解耦作为设计原则
带有依赖项注入的控件倒置从代码中删除了具体的依赖项源。 程序中没有任何地方对Engine
实现进行过硬编码的引用。 这是将解耦作为软件设计原理的一个示例。 将应用程序代码与实现分离开来可使您的代码更易于管理和维护。 该应用程序不太了解其各部分如何装配在一起,但是在应用程序生命周期的任何时候进行更改都容易得多。
@Autowired与@Inject
@Autowired
和@Inject
做同样的事情。 但是,@ @Inject
是Java标准注释,而@Autowired
特定于Spring。 它们都具有相同的目的,即告诉DI引擎使用匹配的对象注入字段或方法。 您可以在Spring中使用任何一个。
Spring框架概述
现在您已经看到了一些Spring代码,让我们来概述一下框架及其组件。 如您所见,该框架包含四个主要模块,这些模块分为多个包。 Spring将为您使用的模块提供相当大的灵活性。
- 核心容器
- 核心
- 豆
- 语境
- 表达语言
- 面向方面的编程(AOP)
- 行动计划
- 方面
- 仪器仪表
- 资料存取与整合
- JDBC
- JPA / ORM
- JMS
- 交易次数
- 网页
- 网络/ REST
- Servlet
- Struts
让我们开始使用两个更常用的Spring功能,而不是在这里介绍所有内容。
启动一个新项目:Spring Boot
我们将使用Spring Boot创建一个示例项目,用于演示Spring功能。 Spring Boot使启动新项目变得更加容易,您将自己看到。 首先,请看下面显示的主类。 在Spring Boot中,我们可以使用main()
方法获取一个主类,然后选择独立运行它,或者选择打包运行在Tomcat之类的容器中。
清单5列出了我们的主类的大纲,这些大纲位于标准的src/main/java/hello
位置。
清单5. Spring Boot的主类
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
请注意上述代码的两件事:首先,所有工作都抽象到框架中。 主类会启动应用程序,但对应用程序的工作方式或交付功能一无所知。 其次, SpringApplication.run()
完成启动应用程序并传递Application
类本身的实际工作。 同样,应用程序所做的工作在这里并不明显。
@SpringBootApplication
批注包装了一些标准批注,并告诉Spring查看组件主类所在的包。 在我们之前的示例中,对于汽车和引擎,这将允许Spring查找所有带有@Component
和@Inject
注释的@Component
。 该过程本身称为组件扫描 ,可以高度自定义。
您可以使用标准的mvn clean install
构建该应用程序,并可以使用Spring Boot目标( mvn spring-boot:run
) mvn spring-boot:run
该应用程序。 在此之前,让我们看一下该应用程序的pom.xml
文件。
清单6.入门pom.xml
<groupId>com.javaworld</groupId>
<artifactId>what-is-spring</artifactId>
<version>1.0.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
</parent>
<dependencies>
</dependencies>
<properties>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
请注意上述代码中的两个重要功能:
-
parent
元素依赖于spring-boot-starter-parent
项目。 该父项目定义了许多有用的默认值,例如JDK 1.8的默认编译器级别。 在大多数情况下,您可以相信它知道自己在做什么。 例如,您可以忽略许多常见依赖项的版本号,SpringBootParent
会将版本设置为兼容。 当增加父级的版本号时,依赖项版本和默认值也会更改。 -
spring-boot-maven-plugin
允许可执行的JAR / WAR打包和就地run
(通过mvn spring-boot:run
命令)。
将Spring Web添加为依赖项
到目前为止,我们已经能够使用spring-boot
来限制spring-boot
和运行应用程序而进行的工作量。 现在,让我们添加一个依赖项,看看在浏览器中获取内容有多快。
清单7.将Spring Web添加到项目
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
注意
Spring将自动检测哪些文件已更改并相应地进行编译。 您只需执行mvn spring-boot:run
即可进行更改。
既然我们已经完成了基本的项目设置,就可以为两个示例做好准备了。
示例2:使用Spring Web构建RESTful端点
我们已经使用spring-boot-starter-web
引入了一些对构建Web应用程序有用的依赖项。 接下来,我们将为URL路径创建路由处理程序。 Spring的Web支持是Spring MVC (模型-视图-控制器)模块的一部分,但是请不要担心:Spring Web也为构建RESTful端点提供了全面而有效的支持。
用来处理URL请求的类称为控制器 ,如清单8所示。
清单8. Spring MVC REST控制器
package hello;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class GreetingController {
@RequestMapping(value = "/hi", method = RequestMethod.GET)
public String hi(@RequestParam(name="name", required=false, defaultValue="JavaWorld") String name, Model model) {
return "Hello " + name;
}
}
@Controller批注
@Controller
批注将一个类标识为控制器。 标记为控制器的类也将自动识别为组件类,这使其成为自动装配的候选对象。 无论何时需要此控制器,都将其插入框架。 在这种情况下,我们将其插入MVC系统以处理请求。
控制器是一种特殊的组件。 它支持您在hi()
方法上看到的@RequestMapping
和@ResponseBody
批注。 这些注释告诉框架如何将URL请求映射到应用程序。
此时,您可以使用mvn spring-boot:run
运行该应用程序。 当您打入/hi
URL时,您将收到类似“ Hello,JavaWorld”的响应。
请注意,Spring是如何利用自动装配组件的基础,并交付了整个Web框架的。 使用Spring,您不必显式地将任何东西连接在一起!
@Request批注
@RequestMapping
允许您定义URL路径的处理程序。 选项包括定义所需的HTTP方法,这是我们在本例中所做的。 离开RequestMethod
将指示程序处理所有HTTP方法类型。
@RequestParam
参数批注允许我们将请求参数直接映射到方法签名中,包括要求某些参数和定义默认值(如此处所做的那样)。 我们甚至可以使用@RequestBody
参数注释将请求主体映射到类。
REST和JSON响应
如果要创建REST端点,并且想从该方法返回JSON,则可以使用@ResponseBody
对该方法进行@ResponseBody
。 然后,响应将自动打包为JSON。 在这种情况下,您将从方法中返回一个对象。
在Spring Web上使用MVC
与Struts相似,Spring Web模块可以轻松地用于真正的模型-视图-控制器设置。 在这种情况下,您将以给定的模板语言(如Thymeleaf )返回映射,而Spring将解析该映射,提供传递给它的模型并呈现响应。
例3:使用JDBC的Spring
现在,让我们对请求处理程序做一些更有趣的事情:让我们从数据库中返回一些数据。 就本示例而言,我们将使用H2数据库 。 幸运的是,Spring Boot开箱即用地支持内存中的H2 DB。
翻译自: https://www.infoworld.com/article/3444936/what-is-spring-component-based-development-for-java.html
java 的春天