这是 学透 Spring Boot 专栏 的第三篇,欢迎关注我,与我一起学习和探讨 Spring Boot 相关知识,学透 Spring Boot。
从面试题说起
今天我们通过一道和Spring Boot有关的常见面试题入手。
面试题:说说
Spring Boot
中有哪些常用注解?
Spring Boot 项目中我们常用的几个注解有:
@SpringBootApplication
:这个注解一般定义在我们项目的启动类上,表示这是项目的入口@EnableAutoConfiguration
:这个注解用来启用 Spring Boot 的自动配置机制,这样就可以根据项目的依赖自动配置 Spring 应用程序@ConfigurationProperties
:这个注解可以把指定的前缀配置项的值绑定到某个JavaBean上@SpringBootTest
:该注解可以更轻松地测试 Spring Boot 应用程序,而不需要必须手动创建应用程序上下文或配置。
是的,到这里就结束了!
因为网上很多 Java 八股文,罗列的是 Spring 的常用注解,而
不是 Spring Boot 的注解
。
面试时你可以放心大胆的这么回答,如果面试官质疑,我们再补充其它的 Spring 注解就可以了,并说明其中的区别,这样可以体现我们对 Spring 的理解。
Spring Boot 常用注解详解
@SpringBootApplication
这是一个组合注解,用于 Spring Boot 应用程序主类,表示这是 Spring Boot 应用程序的入口点。
@SpringBootApplication
public class SkybootApplication {
public static void main(String[] args) {
SpringApplication.run(SkybootApplication.class, args);
}
}
点击这个注解,我们进入到它的注解定义,就可以看到它其实由@SpringBootConfiguration
,@EnableAutoConfiguration
,@EnableAutoConfiguration
三个注解组成的!
@Target
@Retention
等这几个是元注解
其它三个才是重点,他们
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {
@Filter(type = FilterType.CUSTOM,classes = {TypeExcludeFilter.class}),
@Filter(type = FilterType.CUSTOM,classes = {AutoConfigurationExcludeFilter.class}
)})
public @interface SpringBootApplication {
@SpringBootConfiguration
这个注解其实是就是Spring 提供的@Configuration
注解的Spring Boot版本!标注一个类作用Spring Boot应用的配置类。
@Configuration
public @interface SpringBootConfiguration {
@AliasFor(annotation = Configuration.class)
boolean proxyBeanMethods() default true;
}
@EnableAutoConfiguration
这个注解用于启用 Spring Boot 的自动配置机制
,这也是 Spring Boot 最强大的特性之一!
这里只是相当于开关的作用,后续我们会有专门的章节介绍这个注解,从而深入学习Spring Boot的自动配置机制!
@ConfigurationProperties
我们在application.properties定义一些配置,可以通过这个注解把指定前缀的配置加载到某个bean
上。
app.name=skyboot
app.duration=10
通过这个注解
@Configuration
@ConfigurationProperties(prefix = "app")
public class AppConfig {
private String name;
private Integer duration;
常见的Spring Boot就这几个,其它的一些不常用的比如
@ConditionalOnClass
会在自动配置原理章节介绍。
Spring 的核心注解
@Configuration
指定一个类作为配置类。比如我们经常用它来定义数据库数据源
,这样一个DataSource对象就注入到Spring 容器中去了。
@Configuration
public class DataSourceConfig {
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/mydb");
dataSource.setUsername("username");
dataSource.setPassword("password");
return dataSource;
}
}
@ComponentScan
这个注解用于指定 Spring 容器扫描组件的基本包路径。
我们可以通过它配置一个扫描路径,但是没有必要,因为 @SpringBootApplication
默认已经包含这个注解了,默认是并将应用程序主类所在的包及其子包作为默认的扫描范围。
package com.mt.skyboot;
@SpringBootApplication
@ComponentScan(basePackages = "com.mt.skyboot")
public class SkybootApplication {
Spring Web 的注解
@Controller
用来标识一个类作为 Spring MVC 中的控制器(MVC中的C),处理客户端发起的 HTTP 请求,并返回相应的视图或数据。
@Controller
public class WebController {
@GetMapping("/user")
public ModelAndView getUser() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("user"); // 渲染user.jsp
modelAndView.addObject("name", "兰亭序咖啡"); // 向页面传递数据
return modelAndView;
}
}
@RestController
现在很多项目都是前后端分离,很多时候只需要开发 REST API。这时候这个注解就非常有用了。
这样可以直接访问 http://localhost:8080/getAllStudents
,默认返回的是json数组。
@RestController
public class StudentController {
@GetMapping("/getAllStudents")
public List<Student> getAllStudents() {
return studentService.getStudents();
}
}
@RequestMapping
这个注解用于在控制器类或方法上指定处理 HTTP 请求的路径。
这样可以直接访问 http://localhost:8080/student/getAllStudents
。
@RequestMapping("/student")
@RestController
public class StudentController {
@GetMapping("/getAllStudents")
public List<Student> getAllStudents() {
return studentService.getStudents();
}
}
@GetMapping
用于将 HTTP GET 请求映射到特定的处理器方法。
@GetMapping("/hello")
public String hello(){
return "<h1>兰亭序咖啡的Spring Boot专栏</h1>";
}
是 @RequestMapping
的简便写法!
@RequestMapping(path = "/hello", method = RequestMethod.GET)
public String hello(){
return "<h1>兰亭序咖啡的Spring Boot专栏</h1>";
}
另外类似的注解
@PostMapping
@PutMapping
@DeleteMapping
Spring Bean 的注解
@Component
被 @Component
注解标识的类将会由 Spring 容器自动扫描并进行实例化,成为 Spring 应用程序中的一个 Bean。
@Component
public class EmailService {
// 发送邮件方法
}
这个注解是一个泛化的概念,包括了
@Controller
、@Service
、@Repository
等更具体的注解。当一个类不符合以上三种类型的特定类时,可以使用 @Component 注解来标识它。
@Controller
用于标识一个类作为 Spring MVC 控制器。
@Controller
public class ApiController {
@GetMapping("/api/data")
@ResponseBody
public String getData() {
return "{\"name\": \"John\", \"age\": 30}"; // 返回 JSON 数据
}
}
@RestController
结合 @Controller
和 @ResponseBody
,用于创建 RESTful 风格的控制器。
和前面的 @Controller
对比,作用是一样的,但是更简洁!
@RestController
public class ApiController {
@GetMapping("/api/data")
public String getData() {
return "{\"name\": \"John\", \"age\": 30}"; // 返回 JSON 数据
}
}
@Service
在项目中通常会有一些业务逻辑
需要处理,例如用户管理、订单处理、商品管理等。@Service
注解可以用于标识这些业务逻辑处理类。
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public User getUserById(Long id) {
return userRepository.findById(id).orElse(null);
}
}
@Repository
这个注解用于标识数据访问层(DAO 层)中的类,表示这些类负责与数据库进行交互,执行数据访问操作。
@Repository
public class ProductRepository {
public List<Product> findAllProducts() {
// 执行查询操作,返回所有产品的数据列表
}
public void saveProduct(Product product) {
// 执行插入操作,保存产品数据到数据库
}
}
Spring IoC 注解
@Autowired
用于自动装配 Bean,通常与构造函数、Setter 方法或字段一起使用。
@Controller
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/users")
public String getUsers() {
// 调用 UserService 中的方法来获取用户数据
userService.getAllUsers();
return "users";
}
}
@Qualifier
与@Autowired 一起使用,通常用于解决多个实现同一接口或父类的类的依赖注入问题。
public interface PaymentProcessor {
void processPayment(double amount);
}
@Component
@Qualifier("paypal")
public class PaypalPaymentProcessor implements PaymentProcessor {
@Override
public void processPayment(double amount) {
System.out.println("Processing payment via PayPal: $" + amount);
}
}
@Component
@Qualifier("creditCard")
public class CreditCardPaymentProcessor implements PaymentProcessor {
@Override
public void processPayment(double amount) {
System.out.println("Processing payment via Credit Card: $" + amount);
}
}
这个接口有两个实现类,这时候需要使用 @Qualifier
指定使用哪个实现类。
@Service
public class PaymentService {
@Autowired
@Qualifier("paypal") // 指定注入 PaypalPaymentProcessor 类型的 Bean
private PaymentProcessor paymentProcessor;
public void processPayment(double amount) {
paymentProcessor.processPayment(amount);
}
}
扩展知识点
@Controller、@Service、@Repository和@Component的区别
@Controller
、@Service
、@Repository
都可以直接用@Component
替换- 本质上没什么区别,但是用特定的注解标识特定的类,这样代码更容易维护,可读性也更好
@Component
public @interface Repository {
@AliasFor(annotation = Component.class)
String value() default "";
}
@Autowired、@Inject、@Resource的区别
Spring中除了 @Autowired
注解之外,还有其他几个用于依赖注入的注解:
- @Autowired: 这个注解是
Spring框架
提供的,是Spring 中最常用的依赖注入注解之一。- 它可以用于自动装配 Bean,通过类型匹配进行依赖注入。
- 可以与
@Qualifier
注解一起使用,用于解决多个同类型 Bean的注入歧义性。
- @Inject: 这个注解是
JSR-330 规范
中定义的依赖注入注解,在 Java EE 和 Spring 中都可以使用。- 与
@Autowired
注解类似,@Inject 注解也可以用于自动装配 Bean,通过类型匹配进行依赖注入。 - 它是 Spring 的一个替代方案,可以与 @Qualifier 注解一起使用,用于解决多个同类型 Bean 的注入歧义性。
- 与
- @Resource: 这个注解是
Java EE 规范
中定义的依赖注入注解,也可以在 Spring 中使用。- @Resource 注解可以通过名称匹配进行依赖注入,也可以指定 Bean 的名称进行注入。
- 与 @Autowired 和 @Inject 注解不同,@Resource注解不支持 @Qualifier 注解,因此在解决多个同类型 Bean 的注入歧义性时不太方便。
思维导图
最后附上思维导图