1 @Autowired
和 @Resource
@Autowired
和 @Resource
都是Java Spring框架中用于依赖注入(Dependency Injection, DI)的注解,它们都可以帮助Spring容器在初始化bean时自动为其属性赋值。然而,这两个注解之间存在一些差异:
-
@Autowired:
- Spring框架提供的注解。
- 默认情况下,它是按照类型进行自动装配的,也就是说,如果上下文中只有一个与要注入的字段或构造器参数类型匹配的bean,则Spring会自动将这个bean注入到对应的位置上。
- 如果需要按名称装配,可以结合使用
@Qualifier
注解来指定bean的名字。 - 默认情况下,
@Autowired
是必须的,如果没有找到合适的bean则会抛出异常,除非设置其required
属性为false
。
-
@Resource:
- 这个注解来自于JSR-250规范,因此它不仅仅局限于Spring框架,其他遵循该规范的框架也能识别此注解。
- 默认情况下,
@Resource
注解首先尝试按名称进行bean的查找和装配,如果找不到同名bean,则再尝试按类型进行装配。 - 在Spring中,可以通过
name
属性明确指定bean的名称,这样即使有多个相同类型的bean也可以正确注入。 - 与
@Autowired
不同的是,@Resource
不具备required属性,但在默认情况下也是要求必须找到相应的bean,否则也会抛出异常。
总结来说,@Autowired
主要基于类型进行自动装配,而@Resource
则优先考虑名称匹配,其次是类型匹配。根据具体项目需求选择适合的注解有助于简化代码并确保依赖关系的有效管理。
2 @RequestMapping 默认是 get 还是 post
@RequestMapping
注解默认情况下支持所有HTTP方法,包括GET、POST、PUT、DELETE等。如果需要限制请求的方法类型,可以通过在注解中明确指定 method
属性来实现。
例如:
Java
1@RequestMapping(value = "/example", method = RequestMethod.GET)
2public String handleGetRequest() {
3 // 处理 GET 请求
4}
5
6@RequestMapping(value = "/example", method = RequestMethod.POST)
7public String handlePostRequest() {
8 // 处理 POST 请求
9}
在这两个示例中,@RequestMapping
注解分别指定了只处理GET和POST类型的HTTP请求。如果不显式声明method
属性,则同一个URL映射路径会响应任何类型的HTTP请求。
3 如果2 个方法不同,但是请求的 url 一样,它会执行哪个方法
在Spring MVC中,如果两个方法的@RequestMapping
注解映射到同一个URL,但没有明确指定HTTP方法(如GET、POST等),那么当收到请求时,Spring容器会根据实际发起的HTTP请求方法来决定执行哪个方法。
例如:
Java
1@Controller
2public class MyController {
3
4 @RequestMapping("/example")
5 public String handleGetRequest() {
6 // 处理 GET 请求
7 return "get-response";
8 }
9
10 @RequestMapping(value = "/example", method = RequestMethod.POST)
11 public String handlePostRequest() {
12 // 处理 POST 请求
13 return "post-response";
14 }
15}
在这个例子中,对于/example
的GET请求,将执行handleGetRequest()
方法;而对于POST请求,则会执行handlePostRequest()
方法。如果同时有多个方法都指定了相同的URL和HTTP方法,而Spring容器无法确定唯一匹配的方法,则会导致启动失败或运行时错误。
4 springboot 支持 redis 分布式锁
Spring Boot 支持使用 Redis 实现分布式锁,通常有两种方式来实现:
-
基于 Spring Data Redis 手动实现: 使用 Spring Data Redis 提供的
JavaStringRedisTemplate
或RedisTemplate
进行操作。开发者可以手动编写逻辑,利用 Redis 的原子命令如SETNX
(设置并判断不存在)和EXPIRE
(设置过期时间)等构建简单的分布式锁机制。1@Autowired 2private StringRedisTemplate redisTemplate; 3 4public void doSomethingLocked(String lockKey, int expireTimeInSeconds) { 5 // 设置锁的值为一个唯一的标识符,比如当前线程ID 6 String threadId = Thread.currentThread().getId(); 7 8 // 尝试获取锁 9 Boolean lockAcquired = redisTemplate.opsForValue().setIfAbsent(lockKey, threadId); 10 if (lockAcquired) { 11 try { 12 // 设置锁的有效期防止死锁 13 redisTemplate.expire(lockKey, expireTimeInSeconds, TimeUnit.SECONDS); 14 15 // 执行临界区代码 16 // ... 17 } finally { 18 // 在finally块中释放锁,确保即使出现异常也能正确解锁 19 String currentValue = redisTemplate.opsForValue().get(lockKey); 20 if (threadId.equals(currentValue)) { 21 redisTemplate.delete(lockKey); 22 } 23 } 24 } else { 25 // 锁已被其他线程持有,可以尝试重试或直接返回失败 26 } 27}
-
使用第三方库 Redisson: Redisson 是一个在 Java 中广泛使用的 Redis 客户端,它提供了高级数据结构和实用工具类,包括完善的分布式锁实现。
Java1@Autowired 2private RedissonClient redisson; 3 4public void doSomethingLocked(RedissonClient client, String lockName) { 5 RLock lock = redisson.getLock(lockName); 6 try { 7 // 尝试获取锁并设置等待超时时间 8 boolean lockAcquired = lock.tryLock(10, 30, TimeUnit.SECONDS); // 等待10秒,锁有效期30秒 9 if (lockAcquired) { 10 try { 11 // 执行临界区代码 12 // ... 13 } finally { 14 // 释放锁 15 lock.unlock(); 16 } 17 } else { 18 // 获取锁失败 19 } 20 } catch (InterruptedException e) { 21 // 处理中断异常 22 Thread.currentThread().interrupt(); 23 // ... 24 } 25}
通过上述两种方式,Spring Boot 应用程序能够方便地利用 Redis 实现分布式锁功能,以确保在分布式系统中的并发控制和资源同步。Redisson 提供的功能更加丰富和完善,对于复杂场景下的分布式锁需求更为友好。