文章目录
前言
Spring Boot通过大量的注解简化了Java企业级应用的开发,让开发者能够以声明式的方式配置应用程序。本文将系统性地介绍Spring Boot中最重要的注解,帮助开发者深入理解其原理和使用场景。
1. 核心启动注解
@SpringBootApplication
这是Spring Boot最核心的注解,它是一个组合注解,包含了:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
等价于以下三个注解的组合:
@SpringBootConfiguration
:标识这是一个配置类@EnableAutoConfiguration
:开启自动配置@ComponentScan
:开启组件扫描
@EnableAutoConfiguration
自动配置是Spring Boot的核心特性,它会根据类路径下的依赖自动配置Bean:
@EnableAutoConfiguration
@ComponentScan
public class ManualConfiguration {
// 手动配置类
}
@SpringBootConfiguration
继承自@Configuration
,用于标识配置类:
@SpringBootConfiguration
public class AppConfig {
@Bean
public MyService myService() {
return new MyServiceImpl();
}
}
2. 组件注解
@Component及其衍生注解
@Component
最基础的组件注解,标识一个Spring管理的组件:
@Component
public class DataProcessor {
public void process(String data) {
// 处理逻辑
}
}
@Service
业务层组件,语义化更强:
@Service
public class UserService {
public User findById(Long id) {
// 业务逻辑
return new User();
}
}
@Repository
数据访问层组件,提供异常转换功能:
@Repository
public class UserRepository {
@Autowired
private JdbcTemplate jdbcTemplate;
public List<User> findAll() {
return jdbcTemplate.query("SELECT * FROM users",
(rs, rowNum) -> new User(rs.getLong("id"), rs.getString("name")));
}
}
@Controller
控制器组件,处理HTTP请求:
@Controller
public class UserController {
@GetMapping("/users")
public String listUsers(Model model) {
// 返回视图名称
return "user-list";
}
}
@RestController
RESTful控制器,结合了@Controller
和@ResponseBody
:
@RestController
@RequestMapping("/api/users")
public class UserRestController {
@Autowired
private UserService userService;
@GetMapping
public List<User> getAllUsers() {
return userService.findAll();
}
@PostMapping
public User createUser(@RequestBody User user) {
return userService.save(user);
}
}
3. 依赖注入注解
@Autowired
自动装配依赖:
@Service
public class OrderService {
// 字段注入
@Autowired
private UserService userService;
// 构造函数注入(推荐)
private final PaymentService paymentService;
@Autowired
public OrderService(PaymentService paymentService) {
this.paymentService = paymentService;
}
// Setter注入
private EmailService emailService;
@Autowired
public void setEmailService(EmailService emailService) {
this.emailService = emailService;
}
}
@Qualifier
当有多个同类型Bean时,指定具体注入哪个:
@Service
public class NotificationService {
@Autowired
@Qualifier("emailSender")
private MessageSender emailSender;
@Autowired
@Qualifier("smsSender")
private MessageSender smsSender;
}
@Primary
标识优先注入的Bean:
@Component
@Primary
public class DefaultMessageSender implements MessageSender {
// 默认实现
}
4. Web相关注解
请求映射注解
@RequestMapping
通用请求映射:
@RestController
@RequestMapping("/api/products")
public class ProductController {
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public Product getProduct(@PathVariable Long id) {
return productService.findById(id);
}
}
HTTP方法特定注解
@RestController
@RequestMapping("/api/books")
public class BookController {
@GetMapping
public List<Book> getAllBooks() {
return bookService.findAll();
}
@GetMapping("/{id}")
public Book getBook(@PathVariable Long id) {
return bookService.findById(id);
}
@PostMapping
public Book createBook(@RequestBody Book book) {
return bookService.save(book);
}
@PutMapping("/{id}")
public Book updateBook(@PathVariable Long id, @RequestBody Book book) {
book.setId(id);
return bookService.update(book);
}
@DeleteMapping("/{id}")
public void deleteBook(@PathVariable Long id) {
bookService.delete(id);
}
}
参数绑定注解
@PathVariable
绑定URL路径参数:
@GetMapping("/users/{userId}/orders/{orderId}")
public Order getOrder(@PathVariable Long userId,
@PathVariable Long orderId) {
return orderService.findByUserAndId(userId, orderId);
}
@RequestParam
绑定请求参数:
@GetMapping("/search")
public List<Product> searchProducts(
@RequestParam String keyword,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size) {
return productService.search(keyword, page, size);
}
@RequestBody
绑定请求体:
@PostMapping("/users")
public User createUser(@RequestBody User user) {
return userService.create(user);
}
@RequestHeader
绑定请求头:
@GetMapping("/profile")
public UserProfile getProfile(@RequestHeader("Authorization") String token) {
return userService.getProfileByToken(token);
}
5. 配置相关注解
@Configuration
标识配置类:
@Configuration
public class DatabaseConfig {
@Bean
@Primary
public DataSource primaryDataSource() {
return DataSourceBuilder.create()
.url("jdbc:mysql://localhost:3306/primary")
.build();
}
@Bean
public DataSource secondaryDataSource() {
return DataSourceBuilder.create()
.url("jdbc:mysql://localhost:3306/secondary")
.build();
}
}
@Bean
声明Bean:
@Configuration
public class AppConfig {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
@ConditionalOnProperty(name = "app.cache.enabled", havingValue = "true")
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager();
}
}
@Value
注入配置值:
@Component
public class AppProperties {
@Value("${app.name}")
private String appName;
@Value("${app.version:1.0}")
private String appVersion;
@Value("#{systemProperties['user.name']}")
private String userName;
}
@ConfigurationProperties
类型安全的配置绑定:
@ConfigurationProperties(prefix = "app.database")
@Component
public class DatabaseProperties {
private String url;
private String username;
private String password;
private int maxPoolSize = 10;
// getter和setter方法
public String getUrl() { return url; }
public void setUrl(String url) { this.url = url; }
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
public int getMaxPoolSize() { return maxPoolSize; }
public void setMaxPoolSize(int maxPoolSize) { this.maxPoolSize = maxPoolSize; }
}
对应的配置文件:
app:
database:
url: jdbc:mysql://localhost:3306/mydb
username: root
password: password
max-pool-size: 20
6. 条件注解
@Conditional系列
根据条件创建Bean:
@Configuration
public class ConditionalConfig {
@Bean
@ConditionalOnProperty(name = "feature.enabled", havingValue = "true")
public FeatureService featureService() {
return new FeatureServiceImpl();
}
@Bean
@ConditionalOnClass(RedisTemplate.class)
public RedisService redisService() {
return new RedisServiceImpl();
}
@Bean
@ConditionalOnMissingBean
public DefaultService defaultService() {
return new DefaultServiceImpl();
}
}
7. 测试注解
@SpringBootTest
集成测试:
@SpringBootTest
@TestPropertySource(locations = "classpath:test.properties")
class UserServiceTest {
@Autowired
private UserService userService;
@Test
void testCreateUser() {
User user = new User("John", "john@example.com");
User saved = userService.save(user);
assertThat(saved.getId()).isNotNull();
assertThat(saved.getName()).isEqualTo("John");
}
}
@WebMvcTest
Web层测试:
@WebMvcTest(UserController.class)
class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private UserService userService;
@Test
void testGetUser() throws Exception {
User user = new User(1L, "John");
when(userService.findById(1L)).thenReturn(user);
mockMvc.perform(get("/api/users/1"))
.andExpect(status().isOk())
.andExpected(jsonPath("$.name").value("John"));
}
}
@DataJpaTest
JPA层测试:
@DataJpaTest
class UserRepositoryTest {
@Autowired
private TestEntityManager entityManager;
@Autowired
private UserRepository userRepository;
@Test
void testFindByEmail() {
User user = new User("John", "john@example.com");
entityManager.persistAndFlush(user);
Optional<User> found = userRepository.findByEmail("john@example.com");
assertThat(found).isPresent();
assertThat(found.get().getName()).isEqualTo("John");
}
}
8. 事务注解
@Transactional
事务管理:
@Service
@Transactional
public class OrderService {
@Autowired
private OrderRepository orderRepository;
@Autowired
private PaymentService paymentService;
@Transactional(rollbackFor = Exception.class)
public Order processOrder(Order order) {
// 保存订单
Order savedOrder = orderRepository.save(order);
// 处理支付
paymentService.processPayment(order.getPaymentInfo());
return savedOrder;
}
@Transactional(readOnly = true)
public List<Order> getOrderHistory(Long userId) {
return orderRepository.findByUserId(userId);
}
}
9. 异步处理注解
@Async
异步方法执行:
@Service
public class EmailService {
@Async
public CompletableFuture<Void> sendEmail(String to, String subject, String body) {
// 模拟发送邮件
try {
Thread.sleep(1000);
System.out.println("Email sent to: " + to);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return CompletableFuture.completedFuture(null);
}
}
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(25);
executor.setThreadNamePrefix("async-");
executor.initialize();
return executor;
}
}
10. 缓存注解
@Cacheable、@CacheEvict、@CachePut
@Service
public class UserService {
@Cacheable(value = "users", key = "#id")
public User findById(Long id) {
// 从数据库查询
return userRepository.findById(id);
}
@CachePut(value = "users", key = "#user.id")
public User update(User user) {
return userRepository.save(user);
}
@CacheEvict(value = "users", key = "#id")
public void delete(Long id) {
userRepository.deleteById(id);
}
@CacheEvict(value = "users", allEntries = true)
public void clearCache() {
// 清除所有缓存
}
}
11. 定时任务注解
@Scheduled
定时任务:
@Component
@EnableScheduling
public class ScheduledTasks {
@Scheduled(fixedRate = 5000)
public void reportCurrentTime() {
System.out.println("Current time: " + new Date());
}
@Scheduled(cron = "0 0 1 * * ?")
public void performDailyTask() {
// 每天凌晨1点执行
System.out.println("Daily task executed");
}
@Scheduled(fixedDelay = 1000, initialDelay = 2000)
public void performTaskWithDelay() {
// 延迟2秒后执行,之后每次执行完成后延迟1秒再执行
System.out.println("Task with delay executed");
}
}
12. 实际应用示例
让我们通过一个完整的用户管理系统来展示这些注解的综合使用:
实体类
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
@Column(unique = true, nullable = false)
private String email;
// 构造函数、getter、setter省略
}
Repository层
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByEmail(String email);
List<User> findByNameContaining(String name);
}
Service层
@Service
@Transactional
public class UserService {
private final UserRepository userRepository;
private final EmailService emailService;
public UserService(UserRepository userRepository, EmailService emailService) {
this.userRepository = userRepository;
this.emailService = emailService;
}
@Cacheable(value = "users", key = "#id")
public User findById(Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new UserNotFoundException("User not found with id: " + id));
}
@CachePut(value = "users", key = "#result.id")
public User save(User user) {
User savedUser = userRepository.save(user);
emailService.sendWelcomeEmail(savedUser.getEmail());
return savedUser;
}
@CacheEvict(value = "users", key = "#id")
public void delete(Long id) {
userRepository.deleteById(id);
}
}
Controller层
@RestController
@RequestMapping("/api/users")
@Validated
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping
public ResponseEntity<List<User>> getAllUsers(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size) {
Pageable pageable = PageRequest.of(page, size);
Page<User> users = userService.findAll(pageable);
return ResponseEntity.ok(users.getContent());
}
@GetMapping("/{id}")
public ResponseEntity<User> getUser(@PathVariable Long id) {
User user = userService.findById(id);
return ResponseEntity.ok(user);
}
@PostMapping
public ResponseEntity<User> createUser(@Valid @RequestBody User user) {
User savedUser = userService.save(user);
return ResponseEntity.status(HttpStatus.CREATED).body(savedUser);
}
@PutMapping("/{id}")
public ResponseEntity<User> updateUser(@PathVariable Long id,
@Valid @RequestBody User user) {
user.setId(id);
User updatedUser = userService.save(user);
return ResponseEntity.ok(updatedUser);
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
userService.delete(id);
return ResponseEntity.noContent().build();
}
}
总结
Spring Boot的注解系统极大地简化了Java企业级应用的开发。通过合理使用这些注解,我们可以:
- 简化配置:减少XML配置文件,使用注解进行声明式配置
- 提高开发效率:自动装配、自动配置等特性减少了样板代码
- 增强可读性:注解直观地表达了代码的意图和功能
- 便于测试:丰富的测试注解支持各种测试场景
- 功能强大:涵盖了从基础的依赖注入到高级的缓存、异步处理等功能
Spring Boot 注解对比表格
注解 | 标注位置 | 功能 |
---|---|---|
@SpringBootApplication |
类 | Spring Boot应用主类标识,包含@Configuration、@EnableAutoConfiguration、@ComponentScan |
@EnableAutoConfiguration |
类 | 开启Spring Boot自动配置功能 |
@SpringBootConfiguration |
类 | 标识配置类,继承自@Configuration |
@Component |
类 | 标识Spring管理的通用组件 |
@Service |
类 | 标识业务层组件,语义化的@Component |
@Repository |
类 | 标识数据访问层组件,提供异常转换 |
@Controller |
类 | 标识MVC控制器组件,返回视图 |
@RestController |
类 | 标识RESTful控制器,组合@Controller和@ResponseBody |
@Autowired |
字段、方法、构造函数 | 自动依赖注入 |
@Qualifier |
字段、方法参数 | 指定注入特定名称的Bean |
@Primary |
类、方法 | 标识优先注入的Bean |
@RequestMapping |
类、方法 | 通用HTTP请求映射 |
@GetMapping |
方法 | GET请求映射,@RequestMapping的简化版 |
@PostMapping |
方法 | POST请求映射,@RequestMapping的简化版 |
@PutMapping |
方法 | PUT请求映射,@RequestMapping的简化版 |
@DeleteMapping |
方法 | DELETE请求映射,@RequestMapping的简化版 |
@PatchMapping |
方法 | PATCH请求映射,@RequestMapping的简化版 |
@PathVariable |
方法参数 | 绑定URL路径中的变量 |
@RequestParam |
方法参数 | 绑定HTTP请求参数 |
@RequestBody |
方法参数 | 绑定HTTP请求体到对象 |
@RequestHeader |
方法参数 | 绑定HTTP请求头 |
@ResponseBody |
方法、类 | 将方法返回值直接写入HTTP响应体 |
@Configuration |
类 | 标识配置类,包含@Bean方法 |
@Bean |
方法 | 在配置类中声明Bean |
@Value |
字段、方法参数 | 注入配置属性值 |
@ConfigurationProperties |
类 | 类型安全的配置属性绑定 |
@ConditionalOnProperty |
类、方法 | 基于配置属性条件创建Bean |
@ConditionalOnClass |
类、方法 | 基于类存在条件创建Bean |
@ConditionalOnMissingBean |
类、方法 | 当缺少指定Bean时创建Bean |
@ConditionalOnBean |
类、方法 | 当存在指定Bean时创建Bean |
@SpringBootTest |
类 | 标识Spring Boot集成测试类 |
@WebMvcTest |
类 | 标识Web层测试类,只加载MVC相关组件 |
@DataJpaTest |
类 | 标识JPA层测试类,只加载JPA相关组件 |
@MockBean |
字段 | 在测试中创建Mock Bean |
@TestPropertySource |
类 | 指定测试配置文件 |
@Transactional |
类、方法 | 声明事务边界 |
@Async |
方法 | 标识异步执行方法 |
@EnableAsync |
类 | 开启异步处理功能 |
@Cacheable |
方法 | 缓存方法返回结果 |
@CacheEvict |
方法 | 清除缓存 |
@CachePut |
方法 | 更新缓存 |
@EnableCaching |
类 | 开启缓存功能 |
@Scheduled |
方法 | 标识定时任务方法 |
@EnableScheduling |
类 | 开启定时任务功能 |
@Valid |
方法参数 | 开启JSR-303验证 |
@Validated |
类、方法参数 | 开启Spring验证功能 |
@CrossOrigin |
类、方法 | 配置跨域资源共享(CORS) |
@Profile |
类、方法 | 指定特定环境下才激活 |
@Import |
类 | 导入其他配置类 |
@ComponentScan |
类 | 配置组件扫描路径 |
@PropertySource |
类 | 指定属性文件位置 |
@Order |
类、方法 | 指定组件加载顺序 |
@EventListener |
方法 | 标识事件监听器方法 |
@PostConstruct |
方法 | Bean初始化后执行的方法 |
@PreDestroy |
方法 | Bean销毁前执行的方法 |