核心与启动
@SpringBootApplication
:作用:这是一个组合注解,通常放在主启动类上。它等同于同时使用
@Configuration
、@EnableAutoConfiguration
和@ComponentScan
。它是 Spring Boot 应用的入口点,开启了自动配置和组件扫描。
@EnableAutoConfiguration
:作用:开启 Spring Boot 自动配置。它会根据 classpath 中存在的 JAR 包依赖,自动配置相应的 Bean。
@Configuration
:作用:将一个类标记为配置类,用于替代传统的 XML 配置。类中的方法可以用
@Bean
注解来定义 Bean。
@Bean
:作用:用于方法上,声明该方法的返回值应该被注册为 Spring 容器中的一个 Bean。
组件与依赖注入
@Component
:作用:将一个类标记为 Spring 组件,使其能被组件扫描器发现并注册到 Spring 容器中。
@Controller
:作用:用于标记 Web 层组件,处理 HTTP 请求。
@Service
:作用:用于标记业务逻辑层组件。
@Repository
:作用:用于标记数据访问层(DAO)组件,通常用于和数据库交互的类。
@Autowired
:作用:自动装配(依赖注入)。它可以注入 Bean 到字段、构造器或方法参数上。
Web 开发
@RestController
:作用:一个组合注解,等同于
@Controller
+@ResponseBody
。它简化了 RESTful API 的开发,使得方法直接返回 JSON 或 XML 数据。
@RequestMapping
:作用:映射 HTTP 请求到指定的处理器方法或类上。它可以定义 URL 路径、HTTP 方法(
GET
、POST
等)。
@GetMapping
、@PostMapping
、@PutMapping
、@DeleteMapping
:作用:
@RequestMapping
的简化版,分别用于处理GET
、POST
、PUT
和DELETE
请求。
@RequestParam
:作用:将 HTTP 请求参数绑定到方法参数上。
@PathVariable
:作用:将 URL 路径中的变量绑定到方法参数上,常用于 RESTful 风格的 URL。
@RequestBody
:作用:将 HTTP 请求体中的数据(如 JSON)绑定到方法参数上,通常用于处理 POST 和 PUT 请求。
配置与属性绑定
@Value
:作用:用于注入配置文件的属性值。例如,
@Value("${server.port}")
可以注入端口号。
@ConfigurationProperties
:作用:将配置文件中的一组属性(通常以某个前缀开头)批量绑定到一个 Java 对象上,使得配置更加结构化和类型安全。
数据库与事务
@Transactional
:作用:声明一个方法或类需要事务支持。当方法执行完毕后,如果发生异常则回滚,否则提交事务。
调度与异步
@EnableScheduling
:作用:开启对
@Scheduled
注解的支持,用于定时任务。
@Scheduled
:作用:用于方法上,声明该方法应该按固定的频率或特定的 Cron 表达式执行。
@EnableAsync
:作用:开启对
@Async
注解的支持。
@Async
:作用:用于方法上,声明该方法应该异步执行,通常在后台线程池中运行,不会阻塞调用者。
1. 条件化注解(Conditional Annotations)
这些注解是 Spring Boot 自动配置的魔法所在,它们决定了在特定条件下是否创建 Bean。
@ConditionalOnClass
&@ConditionalOnMissingClass
作用:当 classpath 中存在或不存在指定的类时,才加载配置或创建 Bean。
场景:这是实现 Starter 依赖的核心。例如,当你在项目中添加
Kafka
依赖时,spring-boot-starter-kafka
会通过@ConditionalOnClass(KafkaTemplate.class)
自动配置 Kafka 相关的 Bean。
@ConditionalOnProperty
作用:根据配置文件中某个属性的值来决定是否加载配置。
场景:常用于通过配置中心来控制功能开关(Feature Toggle)。
示例:
Java@Configuration @ConditionalOnProperty(name = "feature.enabled", havingValue = "true") public class FeatureConfig { // 当配置项 feature.enabled=true 时,该配置类才会生效 }
@ConditionalOnMissingBean
作用:当 Spring 容器中不存在指定类型的 Bean 时,才创建该 Bean。
场景:这是自定义配置覆盖自动配置的关键。例如,你可以自己定义一个
DataSource
Bean,自动配置的DataSource
Bean 就会因为容器中已存在同类型 Bean 而不会被创建。
2. 事件驱动与异步
@EventListener
作用:它提供了一种简单的方式来监听并处理 Spring 应用中发布的事件。它可以处理任何
ApplicationEvent
或自定义事件。场景:用于解耦业务逻辑。例如,用户注册成功后发布一个事件,其他模块(如发送邮件、生成积分)可以监听这个事件来执行自己的任务,而无需和注册服务直接耦合。
@Async
&@EnableAsync
作用:将一个方法标记为异步执行,它会在一个单独的线程中运行,不会阻塞调用者。
@EnableAsync
必须在配置类上开启。场景:常用于处理耗时操作,例如发送短信、处理日志等,以避免阻塞主线程或请求线程。
3. 测试
Spring Boot 提供了专用的注解来简化测试,它们只加载应用上下文的“一小部分”,以提高测试效率。
@WebMvcTest
作用:用于测试 Web 层(
@Controller
)。它只加载与 Web 相关的组件,如 Controller、Filter 和WebMvcConfigurer
,而不会加载 Service 和 Repository 等。
@DataJpaTest
作用:用于测试 JPA 持久层。它只加载 JPA 相关的组件,如
EntityManager
、TestEntityManager
和Repository
接口,并默认使用嵌入式数据库。
4. 外部化配置
@PropertySource
作用:用于加载非标准
application.properties/yml
文件中的配置。场景:当配置文件放在非默认位置或需要加载多个配置文件时使用。
示例:
Java@Configuration @PropertySource("classpath:app.properties") public class MyConfig { // ... }
5. 其他高级注解
@Profile
作用:将组件或配置标记为在特定环境下才启用。
场景:常用于区分开发、测试和生产环境的 Bean,例如,在开发环境下使用内存数据库,在生产环境使用 MySQL。
@Order
作用:用于控制 Bean 的加载顺序。
场景:当需要确保某个 Bean 在另一个 Bean 之前或之后加载时使用。
@Scope("prototype")
作用:将 Bean 的作用域设置为“原型”,即每次从容器中获取时都创建一个新的实例。
场景:当 Bean 内部维护了状态,且这个状态不希望被多个线程共享时使用。默认作用域是“单例”(Singleton)。
@Before
通知
@Before
通知在目标方法执行之前运行。它就像一个“前置检查”,你可以在方法调用前执行一些操作,比如日志记录或权限验证,但它无法改变方法的执行流程或返回值。
特点:
执行时机:在目标方法执行前。
控制能力:无法阻止方法的执行,也无法改变方法的参数或返回值。
返回值:方法必须返回
void
。
适用场景:
日志记录:记录方法被调用的信息。
权限验证:检查用户是否有权限执行该方法。
事务开始:在方法执行前开启一个事务。
Java
@Aspect
@Component
public class MyBeforeAspect {
@Before("execution(* com.example.service.*.*(..))")
public void logBefore(JoinPoint joinPoint) {
System.out.println("进入方法: " + joinPoint.getSignature().toShortString());
}
}
@Around
通知
@Around
通知是最强大、最灵活的通知类型。它环绕在目标方法执行的周围,可以完全控制方法的执行。你可以把它想象成一个“代理”,它可以在方法调用前、中、后执行任何操作。
特点:
执行时机:环绕在目标方法执行的整个过程。
控制能力:
可以决定是否调用目标方法(通过调用
proceedingJoinPoint.proceed()
)。可以改变传入的参数或方法的返回值。
可以捕获并处理目标方法抛出的异常。
返回值:可以返回任何类型,其返回值将作为调用者的返回值。
适用场景:
性能监控:在方法执行前后记录时间,计算方法耗时。
缓存:在方法执行前检查缓存,如果命中则直接返回,否则执行方法并将结果存入缓存。
事务管理:在方法执行前开启事务,成功后提交,失败后回滚。
Java
@Aspect
@Component
public class MyAroundAspect {
@Around("execution(* com.example.service.*.*(..))")
public Object measureExecutionTime(ProceedingJoinPoint pjp) throws Throwable {
long start = System.currentTimeMillis();
// 调用目标方法
Object result = pjp.proceed();
long end = System.currentTimeMillis();
long duration = end - start;
System.out.println(pjp.getSignature().toShortString() + " 方法执行耗时: " + duration + "ms");
return result;
}
}
总结:如何选择
特性 | @Before |
@Around |
执行时机 | 方法执行前 | 环绕方法执行 |
控制能力 | 无法控制 | 完全控制:可阻止、可改变参数、可改变返回值 |
复杂度 | 简单 | 复杂,需要手动调用 proceed() ,容易出错 |
参数 | JoinPoint |
ProceedingJoinPoint |
返回值 | void |
任何类型 |
推荐用法 | 日志、权限等,不影响业务的方法 | 性能监控、缓存等,需要改变或控制业务流程的方法 |