spring04-管理bean(创建、注入):基于注解

一、什么是注解?

(1)注解的定义

注解(Annotation)是 Java 代码中的一种特殊标记,用于在程序运行或编译时提供元信息

格式:

@注解名(属性名=属性值, 属性名=属性值...)

(2)注解的使用位置

注解可以作用在:

位置示例
类上@Component@Controller
方法上@PostMapping@Bean
属性上@Autowired@Value

(3)为什么要用注解?

以前 Spring 使用 XML 管理 Bean(如 <bean> 标签),太繁琐。

使用注解的目的就是:

  • 减少繁琐 XML 配置

  • 提高开发效率

  • 实现“零 XML”开发(尤其在 Spring Boot 中)

二、Spring 提供的用于创建 Bean 的注解

Spring 提供四个核心注解来创建 Bean:

(1)@Component
(2)@Service
(3)@Controller
(4)@Repository

上面四个注解功能是一样的,都可以用来创建 bean 实例。

第一步,引入AOP依赖

        <!-- Spring AOP --><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>5.3.34</version></dependency>

第二步,在配置文件中,开启组件扫描

要想让这些注解生效,必须启用 组件扫描,告诉 Spring 去哪些包下扫描这些类。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:util="http://www.springframework.org/schema/util"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/utilhttp://www.springframework.org/schema/util/spring-util.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!-- 开启组件扫描 --><context:component-scan base-package="createBean"/>

1、添加context命名空间

2、开启组件扫描

第三步,创建类,在类上添加注解。

2-1、@Component

  • 通用组件注解,表示这个类会被 Spring 容器管理。

  • 最基本的注解,其他三个都是它的“语义化子类”。

这四个注解效果都是一样的,都能实现创建bean,只是语义不同!

@Component
public class UserService {// ...
}

2-2、@Service

  • 用于 业务逻辑层(Service)

  • 语义更清晰,等价于 @Component

@Service
public class OrderService {// 业务处理逻辑
}

2-3、@Controller

  • 用于 控制层(Controller)

  • 和 Spring MVC 一起使用,处理前端请求

@Controller
public class UserController {@RequestMapping("/hello")public String hello() {return "hello.jsp";}
}

2-4、@Repository

  • 用于 数据访问层(DAO)

  • Spring 会对其进行 异常转换(把 JDBC 异常转换为 Spring 的统一异常)

@Repository
public class UserDao {// 数据访问逻辑
}

2-5、总结:这四个注解有什么关系?

注解说明本质上就是 @Component
@Component通用组件,推荐基础类使用
@Service用于 Service 层✅(语义化)
@Controller用于 Web 层控制器✅(语义化)
@Repository用于 DAO 层✅(附带异常转换功能)

2-6、精准控制扫描范围

1、include-filter

2、exclude-filter

三、如何让 Spring 识别这些注解?

要想让这些注解生效,必须启用 组件扫描,告诉 Spring 去哪些包下扫描这些类。

3-1、XML 方式启用注解扫描:

<context:component-scan base-package="com.example"/>

3-2、Java 配置方式:(完全注解开发)

@Configuration
@ComponentScan("com.example")
public class AppConfig {
}

背景:为什么有这段代码?

这是 Spring 在**使用注解配置(纯 Java 配置)**时,替代 XML 配置的一种方式,用来告诉 Spring:

“这是一个 Java 配置类,它会负责创建和管理 Spring 容器中的 Bean。”

此时,可以用配置类,完全替代xml配置文件,实现完全注解开发!


1、@Configuration 注解详解

🟡 作用:

@Configuration

用于声明一个类是 配置类(Configuration Class)等价于以前的 applicationContext.xmlbeans.xml 文件

🟢 本质:

@Configuration 本质上是一个 @Component,因此它本身也会被 Spring 管理为一个 Bean。

  • 会告诉 Spring:“这里面的方法可以用来生成 Bean。”

  • 配合 @Bean 注解使用最常见(手动注册 Bean)

🧠 举例:

@Configuration
public class AppConfig {@Beanpublic UserService userService() {return new UserService();  // 相当于 <bean id="userService" class="..."/>}
}

2、@ComponentScan("com.example") 注解详解

🟡 作用:

告诉 Spring 自动扫描指定包及其子包中的所有注解类(比如 @Component@Service@Controller@Repository),并将它们注册为 Spring 容器中的 Bean。

🟢 类似于 XML 中的配置:

<context:component-scan base-package="com.example"/>

🧠 举例:

@ComponentScan("com.example")

表示扫描 com.example 这个包及其子包中的类。

只要类上有下面这些注解之一:

  • @Component

  • @Service

  • @Controller

  • @Repository

Spring 就会自动创建这些类的实例并放入 IoC 容器。


3、完整代码解释

@Configuration                        // 声明这是一个配置类,代替 XML 配置
@ComponentScan("com.example")        // 扫描 com.example 包下的所有注解 Bean
public class AppConfig {// 此类可以写 @Bean 方法,也可以不写(只做组件扫描)
}

4、使用方式:怎么让它生效?

你需要创建一个 Spring 容器,并传入这个配置类:

// 使用注解方式创建容器(非 XML)
AnnotationConfigApplicationContext context =new AnnotationConfigApplicationContext(AppConfig.class);// 从容器中获取 Bean
UserService userService = context.getBean(UserService.class);
userService.sayHello();

5、进阶补充

(1)、多个包扫描,数组形式!

@ComponentScan(basePackages = {"com.example", "com.other"})

(2)、精准控制扫描范围(排除特定类)

@ComponentScan(basePackages = "com.example",excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class)
)

6、小结对比(XML vs 注解方式)

功能XML 配置注解配置(现代 Spring 推荐)
声明配置文件<beans>@Configuration
声明组件扫描<context:component-scan>@ComponentScan
注册 Bean<bean>@Bean

7、示意图结构:

com.example
├── AppConfig.java          // @Configuration + @ComponentScan
├── controller
│   └── HelloController.java  // @Controller
├── service
│   └── HelloService.java     // @Service
└── dao└── UserDao.java          // @Repository

四、基于注解方式实现属性的注入(Dependency Injection: DI)

Spring 提供多种注解方式来将对象之间的依赖关系注入到类中,最常见的是:

(1)@Autowired

(2)@Qualifier

(3)@Resource(来自 JSR-250,Java 标准)


4-1、@Autowired —— 按类型注入

作用:自动根据类型(byType)在 Spring 容器中查找匹配的 Bean 并注入。

第一步 把 service 和 dao 对象创建,在 service 和 dao 类添加创建对象注解

第二步 在 service 注入 dao 对象,在 service 类添加 dao 类型属性,在属性上面使用注解

示例:

@Component
public class UserController {@Autowiredprivate UserService userService;  // 自动注入 UserService 类型的 Bean
}

如果容器中只有一个 UserService 类型的 Bean,就能正常注入。


支持的注入位置:

  • 属性注入(推荐)

  • 构造函数注入

  • Setter方法注入

1、属性注入(常用):

@Autowired
private UserService userService;

2、构造函数注入:

@Autowired
public UserController(UserService userService) {this.userService = userService;
}

3、Setter注入:

@Autowired
public void setUserService(UserService userService) {this.userService = userService;
}

❗注意:

  • 默认 按类型 注入(byType)

  • 如果找到多个相同类型的 Bean → 会报错(NoUniqueBeanDefinitionException

 

4、可选注入

默认情况下,当我们标记了一个@Autowired后,Spring如果没有找到对应类型的Bean,它会抛出NoSuchBeanDefinitionException异常。

可以给@Autowired增加一个required = false的参数:

@Component
public class MailService {@Autowired(required = false)ZoneId zoneId = ZoneId.systemDefault();...
}

这个参数告诉Spring容器,如果找到一个类型为ZoneId的Bean,就注入,如果找不到,就忽略

这种方式非常适合有定义就使用定义,没有就使用默认值的情况。


4-2、@Qualifier —— 配合 @Autowired 精确指定注入哪一个 Bean(按名字

当容器中有多个相同类型的 Bean 时,用 @Qualifier("beanName") 指定注入哪个。

示例:

@Component("userServiceA")
public class UserServiceA implements UserService {}@Component("userServiceB")
public class UserServiceB implements UserService {}@Component
public class UserController {@Autowired@Qualifier("userServiceA")private UserService userService;  // 明确注入 userServiceA
}

【注意】:

     @Qualifier 只能和 @Autowired 搭配使用


4-3、@Resource —— 按名字注入(来自 JSR-250)

来自 Java 标准规范(javax.annotation.Resource),也被 Spring 支持。

默认注入规则:

  • 先按 名字(byName)找 Bean

  • 如果找不到,再按类型(byType)找。

示例:

@Resource(name = "userService")
private UserService userService;

如果没写 name 属性:

Spring 默认使用变量名作为 Bean 名称:

@Resource
private UserService userService;  // 默认去找名为 "userService" 的 Bean

4-4、三者对比总结:

特性@Autowired@Qualifier@Resource
来自包Spring(org.springframeworkSpringJDK(javax.annotation
注入方式默认按类型(byType)搭配 @Autowired 使用,按名称默认按名称(byName),找不到再按类型
支持位置属性、构造器、方法搭配 @Autowired 使用属性、方法(不推荐构造器)
是否必须默认必须,配合 @Autowired(required = false) 可设为非必须-默认必须,可搭配 @Resource(name="...") 使用

推荐使用方式(Spring 开发建议)

  • 单一 Bean 时:直接用 @Autowired

  • 多个实现类时:用 @Autowired + @Qualifier

  • 需要兼容 JDK 标准规范时:用 @Resource(这不是spring官方的注解,是javax里面的)


4-5、例子完整演示

@Service("userServiceA")
public class UserServiceA implements UserService {}@Service("userServiceB")
public class UserServiceB implements UserService {}@Controller
public class UserController {// 推荐使用方式一@Autowired@Qualifier("userServiceA")private UserService userService;// 或者使用标准注解方式// @Resource(name = "userServiceB")// private UserService userService;
}

4-6、@Value注解

以上的三个注解,都是属性类型是对象的注解,当属性类型是普通数据类型的时候,可以使用@Value注解。

除此以外,@Value还可以注入:

  • 字面量(常量、字符串等)

  • 配置文件中的值(.properties.yml 中)

  • SpEL 表达式(Spring Expression Language)

当然可以!下面是对 @Value 注解的详细讲解,帮助你全面理解它的作用、用法和使用场景:


1、常见使用场景

(1)注入常量值
@Value("Hello Spring")
private String msg;

(2)注入配置文件中的值(最常见

假设有 application.properties 文件:

app.name=SmartCampus
app.version=1.0.2

然后在 Java 类中使用:

@Component
public class AppInfo {@Value("${app.name}")private String appName;@Value("${app.version}")private String version;
}

Spring 会自动从配置文件中找到 app.name 对应的值并注入。


(3)、使用条件

.properties 文件必须加载进 Spring 容器中!!!

如果你使用的是 Spring Boot → 它自动加载了 application.properties不需要额外配置

但如果你是传统 Spring XML 项目:

<context:property-placeholder location="classpath:application.properties"/>

【回顾】:

这是spring加载外部配置文件的方式! 


(4)、支持 SpEL 表达式(计算、引用 Bean 等)

示例 1:表达式计算

@Value("#{5 * 2}")
private int result;  // result = 10

示例 2:引用其他 Bean 的属性

@Value("#{userService.name}")
private String userName;

注意观察#{}这种注入语法,它和${key}不同的是,#{}表示从JavaBean读取属性

示例:"#{smtpConfig.host}"的意思是,从名称为smtpConfig的Bean读取host属性,即调用getHost()方法。

使用一个独立的JavaBean持有所有属性,然后在其他Bean中以#{bean.property}注入的好处是,多个Bean都可以引用同一个Bean的某个属性。


(5)、也可以用在方法或构造器参数
@Component
public class Server {private int port;public Server(@Value("${server.port}") int port) {this.port = port;}
}

(6)、@Value 注入数组、集合

示例:

app.languages=Java,Python,R
@Value("#{'${app.languages}'.split(',')}")
private List<String> languages;

(7)、小结
注解用途
@Value注入属性值(字面量、配置、SpEL)
${}取配置文件中的值
#{}SpEL 表达式(计算、引用等)

五、创建第三方Bean

Spring 中一个非常典型的场景:

如何将一个没有使用 @Component 注解的第三方类(如 HikariDataSource)交给 Spring IoC 容器管理?

因为第三方类你无法直接修改源代码(不能加 @Component),所以不能自动扫描识别。我们需要用 显式注册的方式 告诉 Spring 去创建并管理这个 Bean。


解决方案:使用 @Configuration + @Bean 创建第三方 Bean。

即:

我们自己在@Configuration类中编写一个Java方法创建并返回它,注意给方法标记一个@Bean注解:

你可以在一个 Java 配置类中,手动创建并配置 HikariDataSource,然后交给 Spring 容器管理。


示例代码:创建并注入 HikariDataSource

步骤 1:添加依赖(Spring + HikariCP)

Maven 依赖示例:

<dependency><groupId>com.zaxxer</groupId><artifactId>HikariCP</artifactId><version>5.1.0</version>
</dependency>

步骤 2:配置文件 application.properties

db.url=jdbc:mysql://localhost:3306/test
db.username=root
db.password=123456

步骤 3:Java 配置类 AppConfig.java

@Configuration
@PropertySource("classpath:application.properties")
public class AppConfig {@Value("${db.url}")private String jdbcUrl;@Value("${db.username}")private String username;@Value("${db.password}")private String password;// 手动创建 HikariDataSource@Beanpublic HikariDataSource dataSource() {HikariDataSource ds = new HikariDataSource();ds.setJdbcUrl(jdbcUrl);ds.setUsername(username);ds.setPassword(password);return ds;}// 如果你有 UserService 也可以在这里注入@Beanpublic UserService userService(HikariDataSource dataSource) {return new UserService(dataSource);}
}

【注意】:

Spring对标记为@Bean的方法只调用一次,因此返回的Bean仍然是单例。 


使用方式:

AnnotationConfigApplicationContext context =new AnnotationConfigApplicationContext(AppConfig.class);UserService userService = context.getBean(UserService.class);
userService.doSomething();

小结:创建第三方 Bean 的三种常见方法

方法使用场景示例
@Bean 方法最推荐方式,灵活、清晰、能配置参数@Bean public HikariDataSource dataSource() { ... }
XML 配置传统 Spring 项目可用<bean class="com.zaxxer.hikari.HikariDataSource" .../>

总结:

如果我们想给 UserService 注入一个来自第三方包(如 HikariDataSource)的 Bean:

  • 使用 @Configuration

  • 编写 @Bean 方法创建并配置 HikariDataSource

  • 然后通过构造器或 @Autowired 注入到其他组件中

 【注意】:

        在 Spring Boot 项目中,如果你想将一个第三方类(比如 HikariDataSource)注入到自己的类中,通常你只需要:

1、添加maven依赖

2、使用 @Autowired 就可以注入使用了。

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

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

相关文章

docker安装elasticsearch和kibana

elasticsearch版本和kibana版本需保持一致。这里我使用的都是8.18.2 安装elasticsearch docker-compose.yml networks:es-net: external: true services:elasticsearch:container_name: es01deploy:resources:limits:cpus: 0memory: 0environment:- discovery.typesingle-no…

Python爬虫实战:研究sanitize库相关技术

1. 引言 1.1 研究背景与意义 在当今数字化时代,互联网已成为人们获取信息、交流互动的重要平台。随着 Web 2.0 技术的发展,用户生成内容 (UGC)、社交媒体嵌入、第三方插件等功能极大丰富了网页的内容和交互性,但也带来了严峻的安全挑战。根据 Web 应用安全联盟 (WAS) 的统…

c++ 学习(二、结构体)

目录 一、结构体与const 二、结构体与class的区别 参考链接&#xff1a;69 结构体-结构体中const使用场景_哔哩哔哩_bilibili 一、结构体与const 调用函数的时候&#xff0c;希望这个结构体是可读而不可写的时候&#xff0c;传指针&#xff0c;使用const修饰&#xff0c;方式…

机器学习开篇:算法分类与开发流程

种一棵树最好的时间是十年前&#xff0c;其次是现在。 一、机器学习算法分类 机器学习&#xff08;ML&#xff0c;Meachine Learning&#xff09;是人工智能的核心领域&#xff0c;让计算机从数据中学习规律并做出预测&#xff0c;本文简单介绍机器学习的算法分类和开发流程。…

使用pyflink编写demo并将任务提交到yarn集群

目录 背景 一、pyflink安装 二、编写demo程序 三、提交yarn前准备 四、提交任务 五、踩坑记录 1、提交任务时客户端出现语法错误 2、提交任务时客户端出现lzma包找不到 3、提交任务时客户端出现“org.apache.flink.streaming.api.utils.PythonTypeUtils.getCollectionIn…

Vue 3 最基础核心知识详解

Vue3作为现代前端主流框架&#xff0c;是前后端开发者都应当掌握的核心技能。本篇文章将带你了解vue3的基础核心知识&#xff0c;适合学习与复习 一、Vue 3 应用创建 1.1 创建Vue应用的基本步骤 // main.js import { createApp } from vue // 1. 导入createApp函数 import …

Bootstrap 5学习教程,从入门到精通,Bootstrap 5 Flex 布局语法知识点及案例(27)

Bootstrap 5 Flex 布局语法知识点及案例 Bootstrap 5 提供了强大的 Flexbox 工具集&#xff0c;让布局变得更加简单灵活。以下是 Bootstrap 5 Flex 布局的完整知识点和详细案例代码。 一、Flex 布局基础语法 1. 启用 Flex 布局 <div class"d-flex">我是一个…

HarmonyOS 5智能单词应用开发:记忆卡(附:源码

一、应用概述与核心价值 在语言学习过程中&#xff0c;单词记忆是基础也是难点。本文介绍的智能单词记忆卡应用通过创新的交互设计和科学的学习模式&#xff0c;帮助用户高效记忆单词。应用采用ArkUI框架开发&#xff0c;主要特点包括&#xff1a; 双模式学习系统&#xff1a…

LeetCode--38.外观数列

前言&#xff1a;之前我不是说&#xff0c;我后续可能会讲一下递归吗&#xff0c;现在它来了&#xff0c;这道题会用到回溯的方法&#xff0c;并且比较纯粹哦 解题思路&#xff1a; 1.获取信息&#xff1a;&#xff08;下面这些信息差不多是力扣上面的题目信息了&#xff0c;所…

服务器的安装与安全设置

1&#xff1a;安装操作系统 1、创建虚拟机Win49&#xff08;49为序号&#xff09;&#xff0c;并安装Windows Server 2019操作系统 参考配置&#xff1a;安装系统的分区大小为20GB&#xff0c;其余分区暂不划分&#xff0c; 文件系统格式为NTFS&#…

Sensodrive SensoJoint机器人力控关节模组抗振动+Sensodrive力反馈系统精准对接

Sensodrive成立于2003年&#xff0c;起源于德国航空航天中心&#xff08;DLR&#xff09;的LBR项目。公司由一批传感器技术专家创立&#xff0c;专注于高精度工业扭矩传感器的研发。凭借二十余年的技术积累&#xff0c;Sensodrive将DLR轻型机器人扭矩技术引入工业领域&#xff…

【AI实践】Mac一天熟悉AI模型智能体应用(百炼版)

25.6.29增加Gummy 实时/一句话语音识别25.6.28增加Qwen TTS本地音频和实时播报 背景 准备环境 MacOS M1电脑&#xff08;其他M系列芯片也可以&#xff09; 为了方便python的使用环境&#xff0c;使用Miniconda&#xff1a;下载链接&#xff1a;Download Anaconda Distribution…

WEB安全--Java安全--jsp webshell免杀1

1.1、BCEL ClassLoader 介绍&#xff08;仅适用于BCEL 6.0以下&#xff09;&#xff1a; BCEL&#xff08;Apache Commons BCEL™&#xff09;是一个用于分析、创建和操纵Java类文件的工具库&#xff1b;BCEL的类加载器在解析类名时会对ClassName中有$$BCEL$$标识的类做特殊处…

Valkey与Redis评估对比:开源替代方案的技术演进

#作者&#xff1a;朱雷 文章目录 1 概述1.1内存数据结构存储核心特性1.2主流内存数据结构存储设计与适用场景1.3目前主流内存数据结构存储对比 2 Valkey 说明2.1 哨兵架构设计2.2 集群架构设计2.3 valkey 使用企业和业内生态‌ 3 评估指标4 评估结果 1 概述 内存数据结构存储…

华为云Flexus+DeepSeek征文 | 基于华为云ModelArts Studio安装NoteGen AI笔记应用程序

华为云FlexusDeepSeek征文 | 基于华为云ModelArts Studio安装NoteGen AI笔记应用程序 引言一、ModelArts Studio平台介绍华为云ModelArts Studio简介ModelArts Studio主要特点 二、NoteGen介绍NoteGen简介主要特点 三、安装NoteGen工具下载NoteGen软件安装NoteGen工具 四、开通…

BUUCTF在线评测-练习场-WebCTF习题[BJDCTF2020]Easy MD51-flag获取、解析

解题思路 打开靶场&#xff0c;有个提交框&#xff0c;输入后url会出现我们提交的参数password http://a48577ed-9a1c-4751-aba0-ae99f1eb8143.node5.buuoj.cn:81/leveldo4.php?password123 查看源码并没用发现什么猫腻&#xff0c;抓包在响应头发现了猫腻 hint: select * …

面向对象三大特性深度解析:封装、继承与多态

面向对象三大特性深度解析&#xff1a;封装、继承与多态 思维导图概览 #mermaid-svg-v2u0XIzKotjyXYei {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-v2u0XIzKotjyXYei .error-icon{fill:#552222;}#mermaid-svg-v2…

mmap映射物理内存之三invalid cache

目录 流程设计 invalid 命令 内核态invalid 内核态invalid&#xff0c;用户态mmap物理地址 PAN机制 PAN机制历程 硬件支持 ARMv8.1-PAN 特性 Linux 内核的适配 软件模拟 PAN&#xff08;SW PAN&#xff09; 背景 Linux 的实现 总结 前述刷新cache的流程也同样可…

记忆化搜索(dfs+memo)无环有向图

这是一道可以当作板子的极简记忆化搜索 建立a 是邻接表&#xff0c;其中 a[x] 存储从节点 x 出发能到达的所有节点。 b[x] 记录从节点 x 出发的所有边的权重之和。根据数学原理&#xff0c;我们很容易发现&#xff0c;一个根&#xff08;起点&#xff09;的期望&#xff0c;等…

使用AI豆包写一个车辆信息管理页面

记录一个基本的车辆信息管理页面&#xff0c;由豆包撰写完成&#xff0c;只需要微调页面即可。 主要功能是车辆信息的查询、新增、编辑&#xff0c;项目用到了uniapp、vue3、ts、uni-ui、z-paging 页面效果如下&#xff1a; 以上界面均由豆包生成&#xff0c;完成度非常高&am…