Java Spring的常用注解详解和案例示范

1. Spring 常用注解概述

1.1 @Component

@Component 是 Spring 的基础注解之一,它用于将类标记为 Spring 容器中的一个组件。通过 @Component 注解,Spring 会自动将该类注册为一个 Bean,供依赖注入使用。

使用示例:
@Component
public class UserService {public void performTask() {System.out.println("User service performing task...");}
}

@Component 的作用类似于在 XML 配置中手动定义 `` 标签,但使用注解的方式使得代码更加简洁。

1.2 @Controller

@Controller 注解用于定义 Spring MVC 的控制器,用来处理用户的 HTTP 请求。它是 @Component 的派生注解,主要用于 Web 层。

使用示例:
@Controller
public class UserController {@GetMapping("/user")public String getUser(Model model) {model.addAttribute("name", "John Doe");return "user";}
}

@Controller 可以与其他 MVC 注解(如 @RequestMapping@GetMapping 等)结合使用。

1.3 @Service

@Service 注解同样是 @Component 的派生注解,主要用于标记服务层的类。使用 @Service 注解可以提升代码的语义性,表示该类承担业务逻辑相关的职责。

使用示例:
@Service
public class ProductService {public String getProductInfo() {return "Product Info";}
}

虽然 @Service@Component 的功能相似,但 @Service 注解更加强调其业务逻辑层的角色。

1.4 @Repository

@Repository@Component 的派生注解,专用于数据访问层(DAO),其主要目的是表示该类为数据存取类。Spring 在遇到该注解时,会将类中抛出的数据访问异常(如 SQL 异常)转换为 Spring 的 DataAccessException

使用示例:
@Repository
public class UserRepository {public void saveUser(User user) {// 逻辑保存用户}
}

@Repository 注解有助于更好地处理持久化异常。


2. @Autowired 注解

@Autowired 是 Spring 中最常用的依赖注入注解之一。它可以自动注入 Spring 容器中声明的 Bean,无需开发者手动实例化。@Autowired 默认按照类型(byType)进行注入。

2.1 使用方式

@Autowired 可以应用于构造方法、字段、Setter 方法中。

示例 1:构造器注入
@Component
public class OrderService {private final UserService userService;@Autowiredpublic OrderService(UserService userService) {this.userService = userService;}public void placeOrder() {userService.performTask();System.out.println("Order placed successfully.");}
}
示例 2:字段注入
@Component
public class OrderService {@Autowiredprivate UserService userService;public void placeOrder() {userService.performTask();System.out.println("Order placed successfully.");}
}
示例 3:Setter 注入
@Component
public class OrderService {private UserService userService;@Autowiredpublic void setUserService(UserService userService) {this.userService = userService;}public void placeOrder() {userService.performTask();System.out.println("Order placed successfully.");}
}

2.2 常见问题及解决方案

2.2.1 多个 Bean 注入冲突

问题:当容器中存在多个相同类型的 Bean 时,@Autowired 无法自动判断注入哪个 Bean,从而导致注入冲突。

解决方案:可以使用 @Qualifier 注解来指定注入的 Bean。

@Autowired
@Qualifier("specificUserService")
private UserService userService;
2.2.2 循环依赖

问题:当两个 Bean 相互依赖时,@Autowired 注解可能会导致循环依赖问题。

解决方案:可以通过构造器注入的方式避免循环依赖,或者使用 Spring 的延迟注入机制。

@Autowired
private ObjectProvider<UserService> userServiceProvider;public void someMethod() {UserService userService = userServiceProvider.getIfAvailable();
}

3. @Resource 注解

@Resource 是 Java 自带的 JSR-250 注解。与 @Autowired 类似,@Resource 也用于依赖注入,但它更注重按名称注入(byName)。它可以通过 nametype 属性指定具体的注入对象。

3.1 使用方式

@Resource 可以注解字段和 Setter 方法。

示例 1:字段注入
@Resource(name = "userService")
private UserService userService;
示例 2:Setter 注入
@Resource
public void setUserService(UserService userService) {this.userService = userService;
}

3.2 @Autowired@Resource 的区别

特性@Autowired@Resource
注入方式默认按类型(byType)注入默认按名称(byName)注入
是否支持 @Qualifier支持,通过 @Qualifier 指定具体的 Bean不支持 @Qualifier
是否为 Spring 注解是 Spring 特有注解JSR-250 标准注解,兼容性更好
适用场景Spring 应用程序中用于依赖注入需要与 Java EE 容器兼容时可优先使用

最佳实践:如果仅依赖于 Spring 框架,推荐使用 @Autowired。如果需要兼容 Java EE 或其他框架,@Resource 是更好的选择。


4. 其他常用注解

4.1 @Scope

@Scope 注解用于指定 Spring 容器中 Bean 的作用范围。常用的范围有 singletonprototyperequestsession 等。

使用示例:
@Component
@Scope("prototype")
public class Task {// 每次注入时都会生成新的实例
}

4.2 @PostConstruct@PreDestroy

这两个注解分别用于在 Bean 初始化之后和销毁之前执行特定操作。它们是 JSR-250 的标准注解,常用于资源的初始化和释放。

使用示例:
@Component
public class ResourceLoader {@PostConstructpublic void init() {System.out.println("Resource loaded.");}@PreDestroypublic void cleanup() {System.out.println("Resource cleaned up.");}
}

4.3 @Configuration@Bean

@Configuration 注解用于定义配置类,替代传统的 XML 配置。而 @Bean 注解则用于将方法返回值注册为 Spring 容器中的 Bean。

使用示例:
@Configuration
public class AppConfig {@Beanpublic UserService userService() {return new UserService();}
}

5. 常见问题及解决方案

Spring 框架中的注解虽然能够简化配置和提升开发效率,但在实际应用中,开发者可能会遇到一些常见问题,尤其是在 Bean 注入和配置冲突方面。以下我们将详细分析常见问题的成因,并提供解决方案。


5.1 Bean 注入失败

问题描述

在 Spring 中,当我们使用 @Autowired@Resource 进行依赖注入时,可能会遇到注入失败的情况。这通常表现为以下两种错误:

  1. NoSuchBeanDefinitionException:Spring 容器无法找到要注入的 Bean。
  2. UnsatisfiedDependencyException:Spring 找不到合适的依赖项进行注入。

这些错误通常发生在以下几种情况下:

  • Spring 容器中没有找到被注入的 Bean。
  • 被注入的 Bean 没有使用 @Component@Service 等注解标记为组件。
  • Spring 容器没有扫描到包含该 Bean 的包。

示例代码:

@Component
public class OrderService {@Autowiredprivate UserService userService;public void processOrder() {userService.performTask();System.out.println("Order processed.");}
}

问题分析: 在上面的代码中,OrderService 通过 @Autowired 注入 UserService,但如果 UserService 没有被 Spring 容器扫描到或者没有正确标记为组件(比如缺少 @Component 注解),那么 Spring 将会抛出 NoSuchBeanDefinitionException

解决方案

  1. 检查注解是否正确: 确保被注入的 Bean(如 UserService)使用了正确的注解,比如 @Component@Service@Repository 等。如果缺少这些注解,Spring 容器将无法将类注册为 Bean。

    @Component
    public class UserService {public void performTask() {System.out.println("User service is performing task.");}
    }
    
  2. 确保包路径正确: 确保 Spring 容器扫描了包含 Bean 的包。可以通过在启动类或配置类中使用 @ComponentScan 注解来指定需要扫描的包。

    示例:

    @SpringBootApplication
    @ComponentScan(basePackages = "com.example.project.services")
    public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
    }
    

    如果 UserService 位于 com.example.project.services 包中,使用 @ComponentScan 可以确保该包下的所有 Bean 都能被扫描到。

  3. 使用 @Qualifier 指定 Bean: 在某些情况下,可能存在多个相同类型的 Bean,导致 Spring 不知道应该注入哪个 Bean。这时可以通过 @Qualifier 注解来指定具体的 Bean。

    @Autowired
    @Qualifier("specificUserService")
    private UserService userService;
    

通过确保注解正确使用、包路径配置合理、以及使用 @Qualifier 明确指定 Bean,可以有效解决 Bean 注入失败的问题。


5.2 注解配置与 XML 配置冲突

问题描述

在一些老旧的 Spring 项目中,可能同时使用了基于注解的配置和 XML 配置。当两种配置方式共存时,可能会引发以下问题:

  1. Bean 冲突:同一个 Bean 既通过注解方式定义,又在 XML 中手动配置,导致 Bean 定义重复,出现冲突。
  2. 优先级不明:开发者不清楚注解配置和 XML 配置的优先级,导致配置逻辑不一致。

示例代码:

XML 配置:

<beans><bean id="userService" class="com.example.project.services.UserService"/>
</beans>

注解配置:

@Service("userService")
public class UserService {public void performTask() {System.out.println("User service is performing task.");}
}

问题分析: 在上述示例中,UserService 通过注解 @Service 被定义为 userService,但同时在 XML 中也定义了相同的 Bean 名称。这将导致 Spring 容器在运行时不知道该使用哪一个定义,从而引发冲突。

解决方案

  1. 优先选择一种配置方式: 在 Spring 项目中,推荐使用基于注解的配置方式。通过使用注解配置,不仅减少了 XML 配置的复杂性,也能使得代码更加直观、易于维护。将所有 Bean 的定义都移至注解配置中,避免混用。

  2. 避免 Bean 名称冲突: 如果必须同时使用注解和 XML 配置,确保同一个 Bean 不会在两种配置方式中重复定义。为避免冲突,注解配置的 Bean 名称可以与 XML 配置的名称不同。

    示例:

    修改注解配置的名称:

    @Service("annotatedUserService")
    public class UserService {// ...
    }
    

    这样就可以同时在 XML 中定义另一个 userService Bean。

  3. 理解优先级: Spring 中,XML 配置的优先级高于注解配置。这意味着如果一个 Bean 同时在 XML 和注解中定义,Spring 容器会优先使用 XML 中定义的 Bean。因此,如果希望使用注解定义的 Bean,可以删除对应的 XML 配置,或将 XML 配置中的 Bean 定义注释掉。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/458070.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

医学数据分析中的偏特征图可视化

在医学领域&#xff0c;我们经常需要处理复杂的数据模型&#xff0c;探索特征与目标变量之间的关系。偏特征图(Partial Dependence Plot, PDP)是一种强大的可视化技术&#xff0c;可以帮助我们更好地理解模型的行为。通过这种图形&#xff0c;我们可以直观地观察每个特征对模型…

零一万物新模型Yi-Lightning:超越GPT-4o

10月16日&#xff0c;零一万物发布了最新的旗舰模型Yi-Lightning&#xff08;闪电&#xff09;&#xff0c;在中国大模型中首度超越 GPT-4o。它在国际权威盲测榜单 LMSYS 上取得了显著成绩&#xff0c;超越了硅谷知名 OpenAI 的 GPT-4o-2024-05-13 和 Anthropic Claude 3.5 Son…

关于iPhone 16 Pro评测视频评论区特征的多维度分析

1.项目背景 随着智能手机的迅速发展&#xff0c;消费者在选择新设备时越来越依赖于网络评价和用户反馈&#xff0c;B站作为中国领先的视频分享平台&#xff0c;聚集了大量科技评测内容&#xff0c;其中UP主的评论区成为用户讨论和交流的重要场所&#xff0c;特别是在iPhone 16…

基于SSM的汽车客运站管理系统【附源码】

基于SSM的汽车客运站管理系统&#xff08;源码L文说明文档&#xff09; 目录 4 系统设计 4.1 设计原则 4.2 功能结构设计 4.3 数据库设计 4.3.1 数据库概念设计 4.3.2 数据库物理设计 5 系统实现 5.1 管理员功能实现 5.1.1 管理员信息 5.1.2 车…

【程序员的逆袭】:在失业的阴影下寻找光明

故事摘要 在失业的阴霾中&#xff0c;一位程序员如何通过外包项目重燃希望之火&#xff1f;这个故事讲述了他的谋生手段&#xff0c;如何在压力之下&#xff0c;通过信息差赚取生活所需。 要点 信息的力量&#xff1a;赚钱的关键在于信息差&#xff0c;而非单纯的体力或脑力…

【轻量级聊天应用】Vocechat本地服务器部署结合cpolar异地即时通讯

文章目录 前言1. 拉取Vocechat2. 运行Vocechat3. 本地局域网访问4. 群晖安装Cpolar5. 配置公网地址6. 公网访问小结 7. 固定公网地址 前言 本文主要介绍如何在本地群晖NAS搭建一个自己的聊天服务Vocechat&#xff0c;并结合内网穿透工具实现使用任意浏览器远程访问进行智能聊天…

iTerm2 保持SSH远程连接

1、保持SSH远程连接的稳定&#xff0c;防止因闲置时间过长而断开连接 When idle, send ASCII code 35 every 60 seconds每60秒 输入# 2、客户端设置保持活动 设置客户端每隔60秒发送一次保活信号&#xff0c;总共尝试3次。 vim ~/.ssh/configHost *ServerAliveInterval 60…

python csv库

python csv库 水一水又是一篇&#xff0c;乐 读取 import csv # 打开 CSV 文件 with open(example.csv, moder, newline) as file: csv_reader csv.reader(file) # 读取文件头&#xff08;可选&#xff09; headers next(csv_reader) print(f"Headers: {heade…

w001基于SpringBoot的在线拍卖系统

&#x1f64a;作者简介&#xff1a;多年一线开发工作经验&#xff0c;原创团队&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取&#xff0c;记得注明来意哦~&#x1f339;赠送计算机毕业设计600个选题excel文…

gateway 整合 spring security oauth2

微服务分布式认证授权方案 在分布式授权系统中&#xff0c;授权服务要独立成一个模块做统一授权&#xff0c;无论客户端是浏览器&#xff0c;app或者第三方&#xff0c;都会在授权服务中获取权限&#xff0c;并通过网关访问资源 OAuth2的四种授权模式 授权码模式 授权服务器将授…

【密码学】全同态加密张量运算库解读 —— TenSEAL

项目地址&#xff1a;https://github.com/OpenMined/TenSEAL 论文地址&#xff1a;https://arxiv.org/pdf/2104.03152v2 TenSEAL 是一个在微软 SEAL 基础上构建的用于对张量进行同态加密操作的开源Python库&#xff0c;用于在保持数据加密的状态下进行机器学习和数据分析。 Ten…

CSS基础—网页布局(重点!)

1、两列布局 &#xff08;1&#xff09;概念 经典两列布局是指一种网页布局方式&#xff0c;其中一列宽度固定&#xff0c;另一列宽度自适应。‌ 这种布局方式在网页设计中非常常见&#xff0c;因为它能够提供良好的视觉效果和用户体验。 如图所示&#xff1a; 页面顶部放置一…

网络搜索引擎Shodan(4)

声明&#xff1a;学习视频来自b站up主 泷羽sec&#xff0c;如涉及侵权马上删除文章 声明&#xff1a;本文主要用作技术分享&#xff0c;所有内容仅供参考。任何使用或依赖于本文信息所造成的法律后果均与本人无关。请读者自行判断风险&#xff0c;并遵循相关法律法规。 感谢泷…

【JavaEE】【多线程】volatile,wait/notify

目录 一、volatile关键字1.1 内存可见性1.2 volatile解决内存可见性问题 二、wait和notify2.1 wait2.2 notify2.3 使用例子2.3.1 例子12.3.2 例子二 一、volatile关键字 volatile可以保证内存可见性&#xff0c;只能修饰变量。 1.1 内存可见性 在前面介绍线程不安全原因时介…

大数据开发扩展shell 笔记

大数据开发扩展shell 此笔记来自尚硅谷 学习目标 1 熟悉shell脚本的原理和使用 2 熟悉shell的编程语法 第一节 Shell概述 1&#xff09;Linux提供的Shell解析器有&#xff1a; [atguiguhadoop101 ~]$ cat /etc/shells /bin/sh/bin/bash/sbin/nologin/bin/dash/bin/tcsh/b…

JCSA-Journal of Consumer Affairs

文章目录 一、征稿简介二、重要信息三、服务简述四、投稿须知五、联系咨询 一、征稿简介 二、重要信息 期刊官网&#xff1a;https://ais.cn/u/3eEJNv 三、服务简述 Journal of Consumer Affairs由美国消费者利益委员会&#xff08;ACCI&#xff09;拥有&#xff0c;成立于1…

淘宝商品详情的“侦探游戏”:如何用API接口揭开数据的面纱

在这个充满神秘数据的电商世界里&#xff0c;淘宝商品详情就像是一个个隐藏的宝藏&#xff0c;等待着我们去发掘。而API接口&#xff0c;就是我们的“侦探工具”&#xff0c;帮助我们快速揭开这些宝藏的面纱。今天&#xff0c;我们就来一场幽默的“侦探游戏”&#xff0c;看看如…

炒股VS炒CSGO游戏装备,哪个更好做

这个项目&#xff0c;赚个10%都是要被嫌弃的 虽然天天都在抒发自己对股市的看法&#xff0c;但自己自始至终也没有买进任何一支股票。之所以对这个话题感兴趣&#xff0c;着实是因为手上的游戏搬砖项目也是国际性买卖&#xff0c;跟国际形势&#xff0c;国际汇率挂钩&#xff…

C++线程池手写实现

1.Thread类的封装 封装Thread类&#xff0c;使其可以直接在外部调用对象的start,detach,join和cancel等方法来实现对线程的操作 1.1代码 //Thread.h// // Created by crab on 2024/10/20. //#ifndef THREAD_H #define THREAD_H#include <pthread.h>class Thread { pub…

使用 Docker 管理完整项目:Java、Vue、Redis 和 Nginx 的一站式部署

个人名片 🎓作者简介:java领域优质创作者 🌐个人主页:码农阿豪 📞工作室:新空间代码工作室(提供各种软件服务) 💌个人邮箱:[2435024119@qq.com] 📱个人微信:15279484656 🌐个人导航网站:www.forff.top 💡座右铭:总有人要赢。为什么不能是我呢? 专栏导…