目录:spring-in-action-5-目录下一节: spring-in-action-5-编写基础类和design功能
这节是第一课,我将使用IDEA来初始化Spring Boot项目
Spring注解
Spring应用上下文使用bean作为其基本单位。
过去,spring使用xml文件来实现bean的装配,现在spring提倡使用于xml文件等价的Java配置类来完成相同工作。
1 2 3 4 5 6 7
| <bean id="inventoryService" class="com.example.InventoryService"/>
<bean id="productService" class="com.example.ProductService"/> <constructour-arg ref="inventoryService"/> </bean>
|
等价的Java配置类,使用@Configuration注解来告知Spring这是一个配置类。会在Spring上下文中提供bean
1 2 3 4 5 6 7 8 9 10 11 12 13
| @Configuration public class ServiceConfiguration{ @Bean public InventoryService inventoryService(){ return new InventoryService(); } @Bean public ProductService productService(){ return new ProductService(inventoryService()); } }
|
同时基于Java的配置会带来多项收益。
只有当Spring不能进行自动配置的时候,上面的两种操作才是必要的。
自动配置
spring的自动配置起源于自动装配(autowiring)和组件扫描(component scanning)。见:spring-in-action-4-装配bean
使用组件扫描技术,Spring能够自动发现应用类路径下的组件,并将它们创建成Spring应用上下文中的bean。
使用自动装配技术,Spring能够自动为组件注入它们所依赖的其他bean。
Spring Boot
Spring Boot提供了更强的自动配置能力。它使用了增强方法自动配置(autoconfiguration)。
Spring Boot能够基于类路径中的条目,环境变量,以及其他因素,合理猜测需要配置的组件并将它们装配在一起。
@SpringBootApplication组合注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| package com.zyj.tacocloud;
import com.zyj.tacocloud.Ingredient.Type; import com.zyj.tacocloud.data.IngredientRepository; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean;
@SpringBootApplication public class TacoCloudApplication {
public static void main(String[] args) {
SpringApplication.run(TacoCloudApplication.class, args); }
}
|
@SpringBootApplication
是一个组合注解,它组合了其他3个注解:
@SpringBootConfiguration
:将该类声明为配置类。这样我们可以按需添加基于Java的Spring框架配置。其本质上是@Configuration
注解的特殊形式。
@EnableAutoConfiguration
:启用Spring Boot的自动配置。这个注解告诉Spring Boot自动配置它认为我们会用到的组件 。
@ComponentScan
:启用组件扫描.这样我们就可以对其他类使用@Component``@Controller``@Service
这样的注解.Spring会自动发现它们,并将它们注册为Spring应用上下文中的组件
SpringBoot Application类
作为整个Spring Boot的应用启动类。其包深(package depth)必须要等于会低于其他所有类。不要把启动类放在过深的包里,这会影响Spring Boot的正常启动。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| package com.zyj.tacocloud;
import com.zyj.tacocloud.Ingredient.Type; import com.zyj.tacocloud.data.IngredientRepository; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean;
@SpringBootApplication public class TacoCloudApplication {
public static void main(String[] args) {
SpringApplication.run(TacoCloudApplication.class, args); }
}
|
启动类实际上可以通过extends配置类的方式,在其中配置Spring Boot的一些运行中配置,但是不建议这么做。
如果你有时间,还是新建一个专门的配置类,完成某一项功能的专门配置为好。
@Controller注解
@Controller
注解使得组件扫描将这个类识别为一个组件,这样会创建一个实例作为Spring应用上下文中的bean。
1 2 3 4 5 6 7 8 9 10
| package com.zyj.tacocloud.web;
@Controller public class DesignTacoController { ... }
|
其他类似目的的注解还有:
- @Component
- @Service
- @Repository
@<menthond>
Mapping注解
这包括@GetMapping注解、@PostMapping注解等。它们的作用是向指定视图发送对应的HTPP method请求,比如GET请求,POST请求等等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| package com.zyj.tacocloud;
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping;
@Controller public class HomeController {
@GetMapping("/") public String home() { return "home"; }
public String getHomeMapName() { return home; } }
|
使用@GetMapping注解,表明这个方法将处理请求,并且返回一个String类型的视图名称。
@SpringBootTest注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| package com.zyj.tacocloud;
import org.junit.jupiter.api.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class) @SpringBootTest class TacoCloudApplicationTests {
@Test void contextLoads() { }
}
|
@WebMvcTest注解
它提供比@SpringBootTest粒度更小的测试。
这是Spring Boot提供的一个特殊测试注解。它会让这个测试在Spring Mvc应用的上下文中执行。
它会为Spring MVC应用提供Spring环境的支持。
一般用于,我们需要仿造Spring MVC的运行机制,在其中进行一些测试。
测试类可以注入一个MockMvc,让测试实现mockup。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| package com.zyj.tacocloud.controller;
import com.zyj.tacocloud.HomeController; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.test.web.servlet.MockMvc;
import static org.hamcrest.Matchers.containsString; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
@WebMvcTest(HomeController.class) class HomeControllerTest {
@BeforeEach void setUp() { }
@AfterEach void tearDown() { }
@Autowired private MockMvc mockMvc;
@Test void home() { }
@Test void getHomeMapName() { }
@Test public void testHomePage() throws Exception { mockMvc.perform(get("/")) .andExpect(status().isOk()) .andExpect(view().name("home")) .andExpect(content().string(containsString("Welcome to ..."))); } }
|
DevTools为Spring开发人员提供了一些便利的工具。
- 代码变更后后,应用会自动重启。
- 当面向浏览器的资源(模板、JavaScript、样式表)等发生变化时,会自动刷新浏览器。
- 自动禁用模板缓存
- 如果使用H2数据库,会内置H2控制台
使用某些模板方案,如Thymeleaf、FreeMarker,会缓存模板解析的结果。这样的话,为每个请求提供服务的时候,模板就不用重新解析了。
生产环境中,这是一种很好的特性,会带来一定的性能收益。但在开发环境中,我们最好禁用它,因为不禁用会导致,即使我们手动刷新浏览器,也无法看到模板变更过的效果。
效果等同于自己配置:
DevTools会在运行的时候,自动启动LiveReload服务器。当你浏览器安装LiveReload浏览器插件后,会在模板、图片、样式表、JavaScript等发生变化的时候自动刷新浏览器。
课后作业
模仿前面要求,实际动手来初始化一个Spring Boot项目
见:spring-in-action-5-spring起步-课后作业