Java Spring 常用注解详解(spring各种注解)
wptr33 2025-06-10 02:11 3 浏览
简介
Spring 框架中提供了大量注解用于简化开发、提升代码可读性、实现依赖注入、事务管理、AOP、RESTful API 等功能。
核心注解(IOC 容器管理)
- @Component:标注一个类为组件,由 Spring 容器自动扫描并管理(泛指 Bean)
- @Service:表示业务逻辑组件,功能等同于 @Component,语义更明确
@Service
public class UserService {
public void saveUser() {}
}
- @Repository:表示数据访问组件,功能同 @Component,Spring 会对其进行异常转换
@Repository
public class UserRepository {
// 数据访问逻辑
}
- @Controller:表示 Spring MVC 控制器
@Controller
public class UserController {
// 处理 HTTP 请求
}
- @RestController:等价于 @Controller + @ResponseBody,用于 RESTful API
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping
public List<User> getUsers() {
return Collections.emptyList();
}
}
配套注解:
- @Autowired:自动注入依赖(默认按类型注入)
- @Qualifier:配合 @Autowired 按名称注入
- @Value("${property}"):注入配置文件中的值
- @Primary:多个 Bean 时,标记默认注入的 Bean
- @Lazy:延迟初始化 Bean
优化启动时间,处理资源密集型 bean。
@Bean
@Lazy
public ExpensiveBean expensiveBean() {
return new ExpensiveBean();
}
配置类注解
- @Configuration:标记配置类,等价于 XML 中的 <beans>
- @Bean:声明一个由 Spring 管理的 Bean,常用于第三方类注入
- @ComponentScan:指定包扫描组件(默认扫描当前类所在包及子包)
@Configuration
@ComponentScan("com.example")
public class AppConfig {}
- @Import:引入其他配置类
- @PropertySource:加载指定( .properties 配置文件)
- @EnableAsync 系列:启用异步功能
- @EnableScheduling:启用定时任务
Web 层相关注解(Spring MVC)
- @RequestMapping:映射请求路径(可用于类/方法)
@RequestMapping(value = "/hello", method = RequestMethod.GET)
public String sayHello() {
return "Hello";
}
- @GetMapping / @PostMapping / @PutMapping / @DeleteMapping:请求方法快捷注解
- @RequestParam:获取 URL 参数(例如 ?name=abc)
@GetMapping("/search")
public List<User> search(@RequestParam String name) {
return Collections.emptyList();
}
- @PathVariable:获取路径变量(如 /user/{id})
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
return new User(id);
}
- @RequestBody:获取请求体中的 JSON 数据并反序列化
@PostMapping("/users")
public User createUser(@RequestBody User user) {
return user;
}
- @ModelAttribute:方法参数绑定表单数据
- @ResponseBody:将返回值序列化为 HTTP 响应体(如 JSON)
@GetMapping("/data")
@ResponseBody
public User getData() {
return new User();
}
- @ResponseStatus:指定 HTTP 响应状态码
@PostMapping("/users")
@ResponseStatus(HttpStatus.CREATED)
public User createUser() {
return new User();
}
- @CrossOrigin:处理跨域请求(CORS)
Spring Boot 相关注解
- @SpringBootApplication:核心注解,包含 @Configuration、@EnableAutoConfiguration、@ComponentScan
- @EnableAutoConfiguration:启用自动配置
- @ConfigurationProperties:绑定配置文件到 Java 对象
- @RestControllerAdvice:全局异常处理类
- @SpringBootTest:用于 Spring Boot 测试类
- @TestConfiguration:用于测试场景下的配置类
- @Profile:指定配置或 Bean 仅在某个环境(profile)生效
事务与异步等功能性注解
- @Transactional:事务控制,常用于 Service 层方法
- @EnableTransactionManagement:启用事务管理(如非 Spring Boot 时需显式开启)
- @Async:异步执行方法(配合 @EnableAsync)
- @Scheduled:定时任务执行(配合 @EnableScheduling)
AOP 相关注解
- @Aspect:定义切面类
标记类为切面,定义横切关注点。
场景:日志、权限等横切逻辑。
@Aspect
@Component
public class LoggingAspect {
// 切面逻辑
}
- @Before / @After / @Around:通知方法
定义切点执行的时机。
@Before("execution(* com.example.service.*.*(..))")
public void logBefore() {
System.out.println("Method called");
}
- @Pointcut:定义切点表达式
简化切面配置。
@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceMethods() {}
注解元注解和自定义注解
- @Retention:注解生命周期(源码/编译期/运行时)
- @Target:注解使用范围(方法、字段、类等)
- @Documented:是否生成 Javadoc
- @Inherited:注解是否可被子类继承
用法示例
@CrossOrigin
用于处理 前后端分离 时的 跨域资源共享(CORS)问题。
浏览器基于安全考虑,默认会阻止来自不同源(协议 + 域名 + 端口)的请求。@CrossOrigin 可以显式允许跨域访问。
@CrossOrigin(origins = "http://localhost:3000")
@RestController
public class MyController {
@GetMapping("/hello")
public String hello() {
return "Hello from backend";
}
}
常用属性:
- origins:允许的域名列表(支持多个)
- methods:允许的请求方式(如 GET, POST)
- allowedHeaders:允许的请求头
- maxAge:预检请求缓存时间,单位秒
推荐做法:
统一配置跨域规则而不是在控制器里逐个加 @CrossOrigin,例如通过配置类:
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:3000")
.allowedMethods("*")
.allowedHeaders("*")
.allowCredentials(true);
}
}
@Transactional — 声明式事务管理
用于开启数据库事务,控制方法在事务中执行,支持回滚与提交。
@Service
public class UserService {
@Transactional
public void createUser(User user) {
userRepository.save(user);
// 如果这里抛出 RuntimeException,事务会回滚
}
}
默认行为:
- 默认只对 RuntimeException 或其子类回滚。
- 对 checked 异常不会自动回滚,需手动指定。
注意事项:
- 必须运行在 Spring 管理的 代理对象 上,不能直接调用同类中的 @Transactional 方法。
- 常见失效场景:private 方法、this.xxx() 调用自身、未被 Spring 扫描等。
@Scheduled — 定时任务
用于计划任务调度,可配置任务在固定时间/间隔执行。
启用定时任务
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
创建定时任务类
package com.example.demo.task;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
@Component
public class MyTask {
@Scheduled(fixedRate = 10000)
public void task1() {
System.out.println("每10秒执行一次: " + LocalDateTime.now());
}
@Scheduled(cron = "0/30 * * * * ?")
public void task2() {
System.out.println("每30秒执行一次(cron 表达式): " + LocalDateTime.now());
}
}
常用属性:
- fixedRate:每隔多久执行一次,单位毫秒(从上次开始算)
- fixedDelay:每隔多久执行一次(从上次结束算)
- cron:使用 cron 表达式执行任务
Cron 表达式格式:
秒 分 时 日 月 星期 年(可选)
@Configuration + @Bean
@Configuration
public class AppConfig {
@Bean
public String defaultMessage() {
return "默认消息 Bean";
}
}
注入使用:
@Autowired
private String defaultMessage;
@GetMapping("/bean")
public String beanMessage() {
return defaultMessage;
}
@Value、@Component
@Component
public class PropertyReader {
@Value("${custom.welcome:Hello Default}")
private String welcomeMessage;
public String getWelcomeMessage() {
return welcomeMessage;
}
}
application.yml 配置:
custom:
welcome: 欢迎使用 Spring Boot
控制器调用:
@Autowired
private PropertyReader reader;
@GetMapping("/welcome")
public String welcome() {
return reader.getWelcomeMessage();
}
@Autowired + @Qualifier
目标:有两个实现类,手动指定注入其中一个
接口
public interface MessageSender {
String send();
}
实现类 A
@Component("emailSender")
public class EmailSender implements MessageSender {
public String send() {
return "Email sent";
}
}
实现类 B
@Component("smsSender")
public class SmsSender implements MessageSender {
public String send() {
return "SMS sent";
}
}
使用注入
@RestController
public class SenderController {
@Autowired
@Qualifier("smsSender")
private MessageSender sender;
@GetMapping("/send")
public String send() {
return sender.send();
}
}
@EnableAsync + @Async
在 Spring Boot 中使用异步方法,标准步骤:
- 启用异步功能:添加 @EnableAsync(一般加在主类或配置类上)
- 将方法标记为异步:加上 @Async
- 返回类型为 void、Future<T>、或更推荐的 CompletableFuture<T>
返回类型 | 使用方式 | 是否阻塞 | 获取结果方式 |
void | 只执行,不关心返回 | 否 | 无 |
CompletableFuture<T> | 可选择异步/阻塞等待 | 否 / 是 | .thenApply() / .get() |
Future<T> | 必须调用 .get() 获取结果(阻塞) | 是 | .get() |
用 CompletableFuture<T>,更灵活,支持异步链式调用或 .get() 阻塞等待。
和 .NET 中 async/await 对比
特性 | Java Spring (@Async) | .NET C# (async/await) |
语法简洁性 | 稍繁琐,要显式 .get() | 极简洁,直接用 await |
支持异步链式调用 | CompletableFuture 支持 | Task 和 LINQ 查询语法完美融合 |
线程池控制 | 可配置线程池 Executor | 默认线程池,支持自定义 |
方法声明限制 | 必须是 Spring Bean 的方法,不能内部调用 | 可自由组合(类方法、静态方法等) |
异常传播 | 需要手动处理 .get() 抛出的异常 | 可以用 try-catch 正常处理 |
用于 Web 控制器时效果 | 不能直接异步响应 Web(除非改为 WebFlux) | 完整异步模型,控制器方法可 async 返回响应 |
@Async 更适合“后台异步任务处理”场景,不适合异步 Web 返回响应(需要用 Spring WebFlux)。
示例一:返回void
@Service
public class AsyncService {
@Async
public void runAsync() {
System.out.println("异步线程执行中:" + Thread.currentThread().getName());
}
}
@EnableAsync
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
调用异步方法:
@GetMapping("/async")
public String async() {
asyncService.runAsync();
return "触发异步调用";
}
示例二:使用 CompletableFuture<T> 返回结果
可以像 .NET async/await 一样“一步获取结果”,只不过 Spring 的 .get() 是阻塞的。
@Async
public CompletableFuture<String> doTask() {
return CompletableFuture.completedFuture("结果:" + LocalDateTime.now());
}
@GetMapping("/result")
public String getResult() throws Exception {
return asyncService.doTask().get(); // 阻塞等待结果返回
}
示例三:使用 Future<T>
使用 ExecutorService 提交任务并获取结果
ExecutorService executor = Executors.newFixedThreadPool(1);
Future<String> future = executor.submit(() -> {
Thread.sleep(1000);
return "任务完成";
});
// 阻塞等待
String result = future.get(); // throws InterruptedException, ExecutionException
System.out.println(result);
executor.shutdown();
局限:
- .get() 会阻塞;
- 无法设置回调;
- 无法链式执行;
- 无异常链式处理。
示例四:使用CompletableFuture<T> 的 supplyAsync 方法
基本异步任务执行
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
return "Hello";
});
String result = future.get(); // 阻塞等待
异步任务 + 消费结果
CompletableFuture<Void> future = CompletableFuture
.supplyAsync(() -> "hello")
.thenAccept(result -> System.out.println("结果是:" + result));
异步任务 + 转换结果(链式调用)
CompletableFuture<String> future = CompletableFuture
.supplyAsync(() -> "5")
.thenApply(Integer::parseInt)
.thenApply(num -> num * 2)
.thenApply(Object::toString);
异常处理
CompletableFuture<String> future = CompletableFuture
.supplyAsync(() -> {
if (true) throw new RuntimeException("出错了!");
return "success";
})
.exceptionally(ex -> {
System.out.println("异常: " + ex.getMessage());
return "默认值";
});
多任务并发组合(allOf / anyOf)
CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> "A");
CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> "B");
// 等待全部完成
CompletableFuture<Void> all = CompletableFuture.allOf(f1, f2);
all.join();
System.out.println("结果:" + f1.join() + ", " + f2.join());
合并两个任务结果
CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(() -> 100);
CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(() -> 200);
CompletableFuture<Integer> result = f1.thenCombine(f2, Integer::sum);
System.out.println(result.get()); // 输出 300
自定义线程池
ExecutorService pool = Executors.newFixedThreadPool(4);
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
return "线程池中的任务";
}, pool);
System.out.println(future.get());
pool.shutdown();
模拟后台任务进度查询
@RestController
public class TaskController {
@Autowired
private TaskService taskService;
@GetMapping("/run")
public String run() throws Exception {
CompletableFuture<String> task = taskService.doTask();
return task.get(); // 等待完成
}
}
@Service
public class TaskService {
@Async
public CompletableFuture<String> doTask() throws InterruptedException {
Thread.sleep(3000);
return CompletableFuture.completedFuture("任务完成!");
}
}
相关推荐
- 开发者必看的八大Material Design开源项目
-
MaterialDesign是介于拟物和扁平之间的一种设计风格,自从它发布以来,便引起了很多开发者的关注,在这里小编介绍在Android开发者当中里最受青睐的八个MaterialDesign开源项...
- 另类插这么可爱,一定是…(另类t恤)
-
IT之家(www.ithome.com):另类插图:这么可爱,一定是…OSXMavericks和Yosemite打破了苹果对Mac操作系统传统的命名方式,使用加州的某些标志性景点来替换猫...
- Android常用ADB命令(安卓adb工具是什么)
-
杀死应用①根据包名获取APP的PIDadbshellps|grep应用包名②执行kill命令...
- 微软Mac版PowerPoint测试Reading Order Pane功能
-
IT之家5月20日消息,微软公司昨日(5月19日)发布博文,邀请Microsoft365Insiders成员,测试macOS新版PowerPoint演示文稿应用,重点引入...
- Visual Studio跨平台开发实战(4):Xamarin Android控制项介绍
-
前言不同于iOS,Xamarin在VisualStudio中针对Android,可以直接设计使用者界面.在本篇教学文章中,笔者会针对Android的专案目录结构以及基本控制项进行介绍,包...
- 用云存储30分钟快速搭建APP,你信吗?
-
背景不管你承认与否,移动互联的时代已经到来,这是一个移动互联的时代,手机已经是当今世界上引领潮流的趋势,大型的全球化企业和中小企业都把APP程序开发纳入到他们的企业发展策略当中。但随着手机APP上传的...
- 谷歌P图神器来了!不用学不用教,输入一句话,分分钟给结果
-
Pine发自凹非寺量子位|公众号QbitAI当你拍照片时,“模特不好好配合”怎么办?...
- iOS文本编辑控件UITextField和UITextVie
-
记录一个菜鸟的IOS学习之旅,如能帮助正在学习的你,亦枫不胜荣幸;如路过的大神如指教几句,亦枫感激涕淋!细心的朋友可能已经注意到了,IOS学习之旅系列教程在本篇公众号的文章中,封面已经换成美女图片了,...
- Android入门图文教程集锦(android 入门教程)
-
Android入门视频教程集锦AndroidStudio错误gradientandroid:endXattributenotfound...
- 如何使用Android自定义复合视图(如何使用android自定义复合视图)
-
在最近的一个客户应用中,我遇到了一个需求,根据选定的值来生成指定数量的编辑框字段,这样用户可以输入人物信息。最初我的想法是把这些逻辑放到Fragment中,只是根据选中值的变化来向线性布局容器中增加编...
- 原生安卓开发app的框架frida常用关键代码定位
-
前言有时候可能会对APP进行字符串加密等操作,这样的话你的变量名等一些都被混淆了,看代码就可能无从下手...
- 教程10 | 三分钟搞定一个智能输入法程序
-
一案例描述1、考核知识点网格布局线性布局样式和主题Toast2、练习目标掌握网格布局的使用掌握Toast的使用掌握线性布局的使用...
- (Android 8.1) 功能与新特性(android的功能)
-
和你一起终身学习,这里是程序员AndroidAndroid8.1(API级别27)为用户和开发人员引入了各种新特性和功能。本文档重点介绍了开发人员的新功能。通过本章阅读,您将获取到以下内容:Andr...
- 怎样设置EditText内部文字被锁定不可删除和修改
-
在做项目的时候,我曾经遇到过这样的要求,就是跟百度贴吧客户端上的一样,在回复帖子的时候,在EditText中显示回复人的名字,而且这个名字不可以修改和删除,说白了就是不可操作,只能在后面输入内容。在E...
- 如何阻止 Android 活动启动时 EditText 获得焦点
-
技术背景在Android开发中,当活动启动时,EditText有时会自动获得焦点并弹出虚拟键盘,这可能不是用户期望的行为。为了提升用户体验,我们需要阻止...
- 一周热门
-
-
C# 13 和 .NET 9 全知道 :13 使用 ASP.NET Core 构建网站 (1)
-
因果推断Matching方式实现代码 因果推断模型
-
git pull命令使用实例 git pull--rebase
-
面试官:git pull是哪两个指令的组合?
-
git 执行pull错误如何撤销 git pull fail
-
git fetch 和git pull 的异同 git中fetch和pull的区别
-
git pull 和git fetch 命令分别有什么作用?二者有什么区别?
-
git pull 之后本地代码被覆盖 解决方案
-
还可以这样玩?Git基本原理及各种骚操作,涨知识了
-
git命令之pull git.pull
-
- 最近发表
-
- 开发者必看的八大Material Design开源项目
- 另类插这么可爱,一定是…(另类t恤)
- Android常用ADB命令(安卓adb工具是什么)
- 微软Mac版PowerPoint测试Reading Order Pane功能
- Visual Studio跨平台开发实战(4):Xamarin Android控制项介绍
- 用云存储30分钟快速搭建APP,你信吗?
- 谷歌P图神器来了!不用学不用教,输入一句话,分分钟给结果
- iOS文本编辑控件UITextField和UITextVie
- Android入门图文教程集锦(android 入门教程)
- 如何使用Android自定义复合视图(如何使用android自定义复合视图)
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)
- c语言 switch (34)
- git commit (34)