百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

Java Spring 常用注解详解(spring各种注解)

wptr33 2025-06-10 02:11 16 浏览

简介

Spring 框架中提供了大量注解用于简化开发、提升代码可读性、实现依赖注入、事务管理、AOP、RESTful API 等功能。

核心注解(IOC 容器管理)

  • @Component:标注一个类为组件,由 Spring 容器自动扫描并管理(泛指 Bean
  • @Service:表示业务逻辑组件,功能等同于 @Component,语义更明确
@Service
public class UserService {
    public void saveUser() {}
}
  • @Repository:表示数据访问组件,功能同 @ComponentSpring 会对其进行异常转换
@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
  • 返回类型为 voidFuture<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 支持

TaskLINQ 查询语法完美融合

线程池控制

可配置线程池 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("任务完成!");
    }
}

相关推荐

oracle数据导入导出_oracle数据导入导出工具

关于oracle的数据导入导出,这个功能的使用场景,一般是换服务环境,把原先的oracle数据导入到另外一台oracle数据库,或者导出备份使用。只不过oracle的导入导出命令不好记忆,稍稍有点复杂...

继续学习Python中的while true/break语句

上次讲到if语句的用法,大家在微信公众号问了小编很多问题,那么小编在这几种解决一下,1.else和elif是子模块,不能单独使用2.一个if语句中可以包括很多个elif语句,但结尾只能有一个...

python continue和break的区别_python中break语句和continue语句的区别

python中循环语句经常会使用continue和break,那么这2者的区别是?continue是跳出本次循环,进行下一次循环;break是跳出整个循环;例如:...

简单学Python——关键字6——break和continue

Python退出循环,有break语句和continue语句两种实现方式。break语句和continue语句的区别:break语句作用是终止循环。continue语句作用是跳出本轮循环,继续下一次循...

2-1,0基础学Python之 break退出循环、 continue继续循环 多重循

用for循环或者while循环时,如果要在循环体内直接退出循环,可以使用break语句。比如计算1至100的整数和,我们用while来实现:sum=0x=1whileTrue...

Python 中 break 和 continue 傻傻分不清

大家好啊,我是大田。...

python中的流程控制语句:continue、break 和 return使用方法

Python中,continue、break和return是控制流程的关键语句,用于在循环或函数中提前退出或跳过某些操作。它们的用途和区别如下:1.continue(跳过当前循环的剩余部分,进...

L017:continue和break - 教程文案

continue和break在Python中,continue和break是用于控制循环(如for和while)执行流程的关键字,它们的作用如下:1.continue:跳过当前迭代,...

作为前端开发者,你都经历过怎样的面试?

已经裸辞1个月了,最近开始投简历找工作,遇到各种各样的面试,今天分享一下。其实在职的时候也做过面试官,面试官时,感觉自己问的问题很难区分候选人的能力,最好的办法就是看看候选人的github上的代码仓库...

面试被问 const 是否不可变?这样回答才显功底

作为前端开发者,我在学习ES6特性时,总被const的"善变"搞得一头雾水——为什么用const声明的数组还能push元素?为什么基本类型赋值就会报错?直到翻遍MDN文档、对着内存图反...

2023金九银十必看前端面试题!2w字精品!

导文2023金九银十必看前端面试题!金九银十黄金期来了想要跳槽的小伙伴快来看啊CSS1.请解释CSS的盒模型是什么,并描述其组成部分。...

前端面试总结_前端面试题整理

记得当时大二的时候,看到实验室的学长学姐忙于各种春招,有些收获了大厂offer,有些还在苦苦面试,其实那时候的心里还蛮忐忑的,不知道自己大三的时候会是什么样的一个水平,所以从19年的寒假放完,大二下学...

由浅入深,66条JavaScript面试知识点(七)

作者:JakeZhang转发链接:https://juejin.im/post/5ef8377f6fb9a07e693a6061目录...

2024前端面试真题之—VUE篇_前端面试题vue2020及答案

添加图片注释,不超过140字(可选)...

今年最常见的前端面试题,你会做几道?

在面试或招聘前端开发人员时,期望、现实和需求之间总是存在着巨大差距。面试其实是一个交流想法的地方,挑战人们的思考方式,并客观地分析给定的问题。可以通过面试了解人们如何做出决策,了解一个人对技术和解决问...