1.什么是Spring
1.1 软件开发的真谛:唯一不变的就是变化。
1.2 任何实际的应用程序都是由很多组件组成的,每个组件负责整个应用功能的一部分,这些组件需要与其他的应用元素进行协调已完成自己的任务。当应用程序运行的时候,需要以某种方式创建并引入这些组件。
1.3 Spring的核心是提供了一个容器(container),通常称为Spring应用上下文(Spring application context),它们会创建和管理应用组件。这些组件也成为 Bean,会在Spring应用上下文中装配在一起,从而形成一个完整的应用程序。
1.4 将Bean装配在一起的行为是通过一种基于依赖注入(dependency injection,DI)的模式实现的。此时,组件不会再去创建它所以来的组件并管理他们的生命周期,使用依赖注入的应用依赖于单独的实体(容器)来创建和维护所有的组件,并将其注入到需要它们的bean中。通常,这是通过构造器参数和属性访问方法来实现的。(tip:bean的生命周期由Spring容器来管理维护)
1.5 在核心容器之上,Spring及其一些列的相关库提供了Web框架、各种持久化可选方案、安全框架、与其他系统集成、运行时监控、微服务支持、反应式编程以及众多现代应用开发所需的特性。
1.6 Spring基于XML文件描述各个组件以及它们与组件的关联关系
<bean id="inventoryService" class="org.example.InventoryService"></bean>
<bean id="productService" class="org.example.ProductService">
<constructor-arg ref="inventoryService"></constructor-arg>
</bean>
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
ProductService productService = (ProductService) applicationContext.getBean("productService");
System.out.println("productService = " + productService);
}
1.7 Spring基于Java的配置,与XML配置等价
// @Configuration 注解告知Spring是一个配置类,会为Spring应用上下文提供bean。
@Configuration
public class ServiceConfiguration {
@Bean
public InventoryService inventoryService(){
return new InventoryService();
}
// @Bean注解表明这些方法的返回对象会以bean的形式添加到Spring的应用上下文中(默认情况下,这些bean所对应的beanID与定义的方法名称是相同的)
@Bean
public ProductService productService(){
return new ProductService(inventoryService());
}
}
public static void main(String[] args) {
// ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ServiceConfiguration.class);
ProductService productService = (ProductService) applicationContext.getBean("productService");
System.out.println("productService = " + productService);
}
1.8 在Spring技术中,自动配置起源于自动装配(autowiring)和组件扫描(Component scanning)。借助组件扫描技术,Spring能够自动发现应用类路径下的组件,并将它们创建成Spring应用上下文的bean。借助自动装配技术,Spring能够为组件注入他们所依赖的其他bean。
SpringBoot是Spring框架的扩展提供了很多增强生产效率的方法。最为大家所知的增强方法就是自动配置(autoconfiguration),Spring Boot 能够基于类路径中的条目、环境变量和其他因素合理猜测需要配置的组件并将它们装配在一起。Spring Boot 大幅度减少了构建应用所需的显示配置的数量
2.初始化Spring项目
2.1 Spring项目结构
这是一个典型的Maven或者Gradle项目结构,其中应用的源码放到了 src/main/java 中,测试代码放到了 src/test/java中,而非 Java 资源放到了 src/main/resources 中。这个项目结构介绍一下:
- mvnw和mvnw.cmd:这是Maven包装器(wrapper)脚本。借助这些脚本,即使机器中没有安装Maven,也可以构建项目。
- pom.xml:这是Maven构建规范。
- TacoCloudApplication.java:这个是Spring Boot主类,他会启动该项目。
- application.properties:指定配置属性的文件
- static:存放浏览器静态内容(图片、样式表、JavaScript等)
- templates:存放渲染内容到浏览器的模板文件。
- TacoCloudApplicationTests.java:测试类,可以保证Spring的应用上下文可以成功的加载。
2.2 pom.xml 构建规范
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>sia</groupId>
<artifactId>taco-cloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging> <!--1 打包为jar-->
<name>taco-cloud</name>
<description>Taco Cloud Example</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version> <!--2 SpringBoot版本-->
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>
UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>
UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency> <!--3 Starter依赖-->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>htmlunit-driver</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin> <!--4 SpringBoot插件-->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
tip
jar 元素标识,我们选择将应用构建成一个可执行的JAR文件,而不是WAR文件。传统的 Java Web 应用都是打包 WAR 文件,JAR 只是用来打包库和较少的桌面UI应用。
打包为 JAR 文件是基于云思维做出的选择。尽管 WAR 文件非常适合部署到传统的 JAVA 应用服务器上,但是对于大多数云平台来说它们并不是理想的选择。所有的 Java 云平台都能运行可执行的 JAR 文件。因为 Spring 默认会使用基于 JAR 的打包方式,除非我们明确告诉它其他的方式。元素,表明我们项目要以 spring-boot-starter-parent 作为其父 POM。这个父 POM 为 Spring 项目常用的一些库提供了依赖管理,现在不需要指定依赖管理的版本,因为是通过父 POM 来管理的。 元素,表明我们需要哪些依赖,其中3个依赖的 artifact ID 上都有 starter 这个单词。Spring Boot Starter 依赖的特别之处在于他们本身并不包含库代码,而是传递性的拉去其他的库。这种 start 主要有3种好处。
第一种: 构建文件会显著减少并且更易于管理,因为这样不必为每个所需的依赖库都声明依赖;
第二种:能够根据他们所提供的功能来思考依赖,而不是根据库的名称。如果是开发 Web 应用,只需要添加 web starter 就可以了,而不必添加一堆单独的库在编写 Web 应用。
第三种:不必担心库的版本问题,可以直接相信给定版本的 Spring Boot,传递性引入的库的版本是兼容的。现在只需要关心使用哪个版本的 Spring Boot 即可。
最后构建规范还包含一个 Spring Boot 插件。这个插件提供了一些重要功能。提供了一个 Maven Goal,允许我们使用 Maven 来运行应用,确保依赖的所有库都在可执行 JAR 文件中,并且能够保证他们在运行是类路径下是可用的。会在 JAR 中生成一个 mainfest 文件,将引导类声明为可执行 JAR 的主类。
2.3 引导应用
我们将会通过可执行 JAR 文件的形式来运行应用,所以很重要的一点就是要有一个主类,他将会在 JAR 运行的时候执行。我们同时还需要一个最小化的 Spring 配置,以引导该应用。这就是 TacoCloudApplication 类所做的事情。
@SpringBootApplication // <1>
public class TacoCloudApplication {
public static void main(String[] args) {
SpringApplication.run(TacoCloudApplication.class, args); // <2>
}
}
在 TacoCloudApplication 中只有很少的代码,但是它包含了很多内容。其中最强大的一行代码也是最短的。@SpringBootApplication注解包含了明确表明这是一个 SpringBoot应用。但是@SpringBootApplication远比看上去更强大。
@SpringBootApplication 是一个组合注解,它组合了三个其他的注解。
- @SpringBootConfigruation:将该类声明为配置类。尽管这个类目前还没有太多的配置,这个注解其实是 @Configuration 注解的特殊形式。
- @EnableAutoConfiguration:启用 Spring Boot 的自动配置。
- @ComponentScan:启用组建扫描。这个就可以使用 @Component、@Service、@Controller这样的注解声明其他类了,Spring 会自动发现它们并将它们注册为 Spring 应用上下文中的组件。
TacoCloudApplication 另外一个很重要的地方是它的 main() 方法。这个是 JAR 文件执行的时候要运行的方法。在大多数情况下,这个方法都是样板代码,我们编写的每一个 Spring Boot 应用都会有一个类似或完全相同的方法。在这个main()方法毁掉一个 SpringApplication.run()方法,会真正执行应用的引导过程,也就是创建Spring的应用上下文。
2.4 测试应用
@RunWith(SpringRunner.class) // <1> 使用Spring的运行器
@SpringBootTest // <2> SpringBoot 测试
public class TacoCloudApplicationTests {
@Test // <3> 测试方法
public void contextLoads() {
}
}
测试类执行时会进行必要的检查,确保Spring应用上下文能够成功加载。
@RunWith(SpringRunner.class)注解:@RunWith 是 JUnit 的注解,它会提供一个测试运行器(runner)来指导 JUnit 如何运行,SpringRunner 是 Spring 提供的测试运行器,会创建测试运行所需的 Spring 应用上下文。
@SpringBootTest注解:会告诉JUnit再启动的时候添加上 Spring Boot 的功能。