3. Spring 注解存储对象 Bean的命名规范

从Java5.0开始,Java开始支持注解。Spring做为Java生态中的领军框架,从2.5版本后也开始支持注解。相比起之前使用xml来配置Spring框架,使用注解提供了更多的控制Spring框架的方式。

SpringFramework版本对应jdk版本重要特性
SpringFramework 1.xjdk 1.3基于 xml 的配置
SpringFramework 2.xjdk 1.4改良 xml 文件、初步支持注解式配置
SpringFramework 3.xJava 5注解式配置、JavaConfig 编程式配置、Environment 抽象
SpringFramework 4.xJava 6SpringBoot 1.x、核心容器增强、条件装配、WebMvc 基于 Servlet3.0
SpringFramework 5.xJava 8SpringBoot 2.x、响应式编程、SpringWebFlux、支持 Kotlin

1. 配置扫描路径

添加下面配置语句到配置文件中:

<content:component-scan base-package="org.example"></content:component-scan>

base-package="org.example"表示注册扫描的包

image.png

对Bean对象的查找只会在这个路径以及它的所有子路径中。设计者的目的是为了缩小扫描的范围,节省开销,提高性能。

配置作用:

  1. 扫描包内及其子包内的所有“类”(不包含接口),并为添加了@Service、@Component、@Controller、@Repository修饰的类创建对象并存入IOC容器

  2. @Service、@Component、@Controller、@Repository修饰的类中含有@Autowired修饰的成员变量,则创建对象时会从IOC容器中取值为该成员变量赋值

这里先提一嘴,后续慢慢道来。。

此时的整个配置文件是长这样的:

<?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:content="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <content:component-scan base-package="org.example"></content:component-scan>
</beans>

2. 添加注解存储 Bean 对象

想要将对象存储在Spring中,有两种注解类型可以实现:

五大类注解:@Controller、@Service、@Repository、@Configuration、@Component

以及方法注解:@Bean

通过注解存储bean对象:

@Controller
public class UserController {
    public void doController() {
        System.out.println("I'm controller.");
    }
}

3. 取出Bean

这里我们使用下面这种getBean()方法,和只传String的参数差不多,但是下面这种方式不需要强转类型,可读性更高:

image.png

3.1 Bean的默认命名

在使用getBean方法的时候开始犯难了,这个Bean对象的id是什么呢?

在Spring中,以注解形式存储的对象,id默认为类名的小驼峰形式,比如"UserController"类,它的id就是"userController"

3.2 使用Bean

public class Application {
   public static void main(String[] args) {
       ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
       UserController userController =
               context.getBean("userController", UserController.class);
       userController.doController();

   }
}

image.png

3.3 Bean的特殊命名【3.1补充】

学会使用Bean之后,我们需要给Bean的命名规则进行一个填坑

特殊情况:当我把类命名为"UController"的时候,再用上面那种方式去找"uController"就会找不到 Bean:


public static void main(String[] args) {
    ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
    UserController userController =
            context.getBean("userController", UserController.class);
    userController.doController();

    UController uController =
            context.getBean("uController", UController.class);
}

image.png

查看一下Bean名称命名的源码:

protected String buildDefaultBeanName(BeanDefinition definition) {
    String beanClassName = definition.getBeanClassName();
    Assert.state(beanClassName != null, "No bean class name set");
    String shortClassName = ClassUtils.getShortName(beanClassName);

//发现这里调用了jdk中的方法,传入BeanName的参数:

    return Introspector.decapitalize(shortClassName);
}

点进去查看一下decapitalize()方法:

public static String decapitalize(String name) {
    //如果name 为空,直接返回原name
    if (name == null || name.length() == 0) {
        return name;
    }
    //如果第一个字母和第二个字母都是大写的情况下,直接返回原name
    if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) &&
                    Character.isUpperCase(name.charAt(0))){
        return name;
    }
    //否则将第一个字符转为小写
    char chars[] = name.toCharArray();
    chars[0] = Character.toLowerCase(chars[0]);
    return new String(chars);
}

看了上面的源码,我们终于豁然开朗,原来当第一个字母和第二个字母都是大写的情况下,Bean的Id并不需要改变:

4. 五大类注解的关系

  1. @Controller【控制器】:前后端交互的第一层 ,前端的数据一定是先到Controller层的
  2. @Service【服务】:第二层,负责服务的编排和汇总
  3. @Repository【仓库】:第三层,负责直接操作数据库
  4. @Configuration【配置】:项目的所有配置
  5. @Component【组件】:通用化的工具类

查看下面四种类注解的实现,它们都带着一个@Component的注解 :

结论:@Controller、@Service、@Repository、@Configuration都是基于@Component实现的,它们都作用都是将 Bean 存到 Spring 中

5. 方法注解@Bean

方法注解是用来修饰方法的,它会将该方法所返回的对象存入Spring中

注意事项:

  • 方法注解必须配合五大类注解使用,否则在取 Bean 的时候会出现找不到 Bean 对象的问题
  • 方法必须是无参的

5.1 方法注解存取对象

创建一个user的model类:

public class User {
    private int userId;
    private String userName;
    private int age;
    //记得generate一下getter和setter以及toString方法
    //...
}

存储Bean:

//搭配任意类注解
@Component
public class GetUserBean {

    @Bean
    User user() {
        User user = new User();
        user.setUserId(1);
        user.setUserName("zhangsan");
        user.setAge(19);
        return user;
    }
}

取出Bean:

image.png

5.2 @Bean的命名

跟五大类注解不一样,Bean的Id是根据方法名按照前面所提到的命名规则得到的:
为什么Bean根据方法名来命名呢?

因为不同的方法返回相同类型的对象是一件很常见的事情,设计者考虑到这点,因此通过@Bean注解存储的Bean的Id是根据方法名来命名。

5.2.1 常见问题

但是与类名不同,在不同类中,有同样的方法名也不是一件奇怪的事,遇到了这种情况会怎么样呢?

@Component
public class GetUserBean {
    @Bean
    User user() {
        User user = new User();
        user.setUserId(1);
        user.setUserName("GetUserBean类:zhangsan");
        user.setAge(19);
        return user;
    }
}
@Component
public class GetUserBean_cp {
    @Bean
    User user() {
        User user = new User();
        user.setUserId(1);
        user.setUserName("GetUserBean_cp类:zhangsan");
        user.setAge(19);
        return user;
    }
}

结果发现并没有报错,结果如下:

image.png

但是这种结果并不是我们想要的,既然我们存了两个bean对象,应该在不同场景需要用不同的bean对象,接下来我们将这个问题的解决方案。

5.2.2 解决方案

通过给@Bean注解传参数取别名:
valuename参数都是用来修改被标注bean在IOC容器中的id属性。并且取别名后原来的方法名的id就用不了了。

@Component
public class GetUserBean {
    @Bean(value = "user_default")
    User user() {
        //....省略代码
    }
}
@Component
public class GetUserBean_cp {
    @Bean(value = "user_cp")
    User user() {
        //....省略代码
    }
}

列举所有取别名写法:

  • value:@Bean(value = "user_cp")
  • name:@Bean(name = "user_cp")
  • 无参:@Bean("user_cp")
  • 多个id:@Bean({"user_cp", "student", teacher"})

使用不同的id取Bean:

image.png

6. 总结

本章节我们学习了:

  • Spring通过注解的方式存储对象,只需要在注解中配置一个扫描路径,简化了在xml文件中配置bean对象的步骤
  • 初步了解了五大类注解@Controller、@Service、@Repository、@Configuration、@Component以及一个方法注解@Bean的使用
  • 类注解和方法注解命名规范以及区别

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux——fork复制进程

1)shell: 在计算机科学中&#xff0c;Shell俗称壳&#xff08;用来区别于核&#xff09;&#xff0c;是指“为使用者提供操作界面”的软件&#xff08;command interpreter&#xff0c;命令解析器&#xff09;。它类似于DOS下的COMMAND.COM和后来的cmd.exe。它接收用户命令&…

练习题(2024/4/10)

1. 删除有序数组中的重复项 给你一个 非严格递增排列 的数组 nums &#xff0c;请你 原地 删除重复出现的元素&#xff0c;使每个元素 只出现一次 &#xff0c;返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。 考虑 nums 的唯一元…

安装VMware ESXi虚拟机系统

简介&#xff1a;ESXi是VMware公司开发的一款服务器虚拟化操作系统。它能够在一台物理服务器上运行多个虚拟机&#xff0c;每个虚拟机都可以独立运行操作系统和应用程序&#xff0c;而且对硬件配置要求低&#xff0c;系统运行稳定。 准备工具&#xff1a; 1.8G或者8G以上容…

查看TensorFlow已训模型的结构和网络参数

文章目录 概要流程 概要 通过以下实例&#xff0c;你将学会如何查看神经网络结构并打印出训练参数。 流程 准备一个简易的二分类数据集&#xff0c;并编写一个单层的神经网络 train_data np.array([[1, 2, 3, 4, 5], [7, 7, 2, 4, 10], [1, 9, 3, 6, 5], [6, 7, 8, 9, 10]]…

MySQL高级(索引结构Hash,为什么InnoDB存储引擎选择使用B+tree索引结构?)

目录 1、Hash索引结构 2、Hash索引特点 3、存储引擎支持 4、为什么InnoDB存储引擎选择使用Btree索引结构&#xff1f; 1、Hash索引结构 哈希索引就是采用一定的hash算法&#xff0c;将键值换算成新的hash值&#xff0c;映射到对应的槽位上&#xff0c;然后存储在hash表中。 如…

吴恩达机器学习-异常检测(Anomaly Detection)

在本练习中&#xff0c;您将实现异常检测算法&#xff0c;并将其应用于检测网络上出现故障的服务器。 文章目录 1-包2-异常检测2.1问题陈述2.2数据集2.3高斯分布2.2.1高斯实现的估计参数&#xff1a;2.2.2选择阈值&#x1d716; 2.4高维数据集 1-包 首先&#xff0c;让我们运…

脑电放大 LM386

LM386介绍 LM386 是一种音频集成功放&#xff0c;具有自身功耗低、电压增益可调整电源电压范围大、外接元件少和总谐波失真小等优点&#xff0c;广泛应用于录音机和收音机之中。 电源电压 4-12V 或 5-18V(LM386N-4);静态消耗电流为 4mA;电压增益为20-200dB;在引脚1和8开路时&a…

Android开发基础:事件传递 基于监听器的事件处理 基于回调的事件处理

目录 一&#xff0c;事件传递机制 1.事件传递机制的三个方法 &#xff08;1&#xff09;public boolean dispatchTouchEvent&#xff08;MotionEvent event&#xff09; &#xff08;2&#xff09;public boolean onInterceptTouchEvent&#xff08;MotionEvent event&…

【C++题解】1601. 挖胡萝卜

问题&#xff1a;1601. 挖胡萝卜 类型&#xff1a;基本运算、小数运算 题目描述&#xff1a; 小兔朱迪挖了 x 个胡萝卜&#xff0c;狐狸尼克挖到胡萝卜数量是小兔挖到的 3 倍&#xff0c;小羊肖恩挖到胡萝卜的数量比狐狸尼克少 8 个。 请你编程计算一下狐狸尼克和小羊肖恩分别…

时间系列预测总结

转载自&#xff1a;https://mp.weixin.qq.com/s/B1eh4IcHTnEdv2y0l4MCog 拥有一种可靠的方法来预测和预测未来事件一直是人类的愿望。在数字时代&#xff0c;我们拥有丰富的信息&#xff0c;尤其是时间序列数据。 时间序列是指基于时间刻度维度&#xff08;天、月、年等&…

Mybatis plus 使用通用枚举

说明&#xff1a;mybatis plus 使用枚举可实现数据库存入时指定值保存&#xff0c; 读取时指定值展示&#xff08;返给前端&#xff09; 可通过继承IEnum<T>、 EnumValue实现 1、引包 <dependency><groupId>mysql</groupId><artifactId>mysql-…

java基础语法(16)| 集合

前言 Hello,大家好!很开心与你们在这里相遇,我是一个喜欢文字、喜欢有趣的灵魂、喜欢探索一切有趣事物的女孩,想与你们共同学习、探索关于IT的相关知识,希望我们可以一路陪伴~ 1. 集合概述 什么是集合 集合:集合是java中提供的一种容器,可以用来存储多个数据,并且可以存…

每天五分钟深度学习PyTorch:面对Tensorflow,为何我选择PyTorch

这篇专栏文章不是为了挑起tenserflow和pytorch中哪个更好&#xff0c;众所周知tensorflow诞生以来&#xff0c;已经成为最流行的深度学习框架&#xff0c;可以说github中大多数的深度学习代码实现是以tensorflow实现的&#xff0c;也就是说资源众多&#xff0c;社区强大&#x…

自动化测试十大必备(背)面试题!【含答案精讲】

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

OJ 最大奖励 C Python【贪心算法】【动态规划】

又接触到贪心算法啦&#xff0c;这道题有两种算法思路&#xff0c;我用两个语言来写了一下&#xff0c;这也涉及到了一些动态规划的思路 一.从最后一个时间枚举&#xff0c;找到在这个时间内可以完成的最大分值的题 注意点&#xff1a; 1.数组下标从1开始记录表示第几个时间…

渲染农场实时画面怎么设置?云渲染农场实时预览效果查看

许多用户在使用渲染农场服务时&#xff0c;常常难以找到查看实时渲染画面的功能。由于渲染是一个时间消耗较大的任务&#xff0c;如果最终结果与预期不符&#xff0c;可能会对整个工作流程产生负面影响。因此&#xff0c;渲染平台若能提供实时预览渲染进度和效果的功能&#xf…

冯喜运:4.10晚间黄金原油走势分析

黄金消息技术面分析&#xff1a;美国CPI年率创半年新高&#xff0c;美国3月未季调CPI年率录得3.5%&#xff0c;高于预期的3.4%水平&#xff0c;为2023年9月以来最高水平。美国CPI高于预期&#xff0c;现货黄金短线下挫16美元。日线当前的指标macd依旧属于金叉放量运行&#xff…

Spring与SpringBoot的区别

Spring是一个开源的Java应用程序框架&#xff0c;旨在简化企业级Java应用程序的开发。它提供了一个轻量级的容器&#xff0c;用于管理应用程序中的各个组件&#xff08;如依赖注入、AOP等&#xff09;&#xff0c;并提供了丰富的功能和模块&#xff0c;用于处理数据库访问、事务…

提醒|2024年CSC国家公派访问学者项目开始网申(附常见申报问题解答)

留学基金委&#xff08;CSC&#xff09;2024年国家公派高级研究学者、访问学者项目网上申报时间为4月10日—4月30日。为此&#xff0c;知识人网小编提醒申请者及时申报。本文我们将常见申报问题汇总解答&#xff0c;以帮助申请者顺利完成CSC申报工作&#xff0c;并预祝红榜题名…

python pygame事件与事件处理

本期是接上期python pygame库的略学内容最后一个步骤&#xff0c;游戏与玩家交互的内容。 一、什么是事件 游戏需要与玩家交互&#xff0c;因此它必须能够接收玩家的操作&#xff0c;并根据玩家的不同操作做出有针对性的响应。程序开发中将玩家会对游戏进行的操作称为事件&…