2023.11.6 Spring 使用注解存储 Bean 对象

news2024/11/26 4:25:14

目录

前置工作

使用类注解

五大类注解 

@Controller(控制器)

@Service(服务)

@Repository(仓库)

@Component(组件)

@Configuration(配置)

使用方法注解 @Bean

重命名 Bean 

补充问题

类注解之间的关系


前置工作

  • 在配置文件中配置好扫描路径

<?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">
    <!--base-package 表示要扫描的路径-->
    <content:component-scan base-package="com.java.demo"></content:component-scan>
</beans>

使用类注解

五大类注解 

@Controller(控制器)

  • 归属业务逻辑层
  • 验证用户请求的数据正确性(安保系统)

@Service(服务)

  • 归属服务层
  • 编排和调度具体的执行方法(客服中心)

@Repository(仓库)

  • 归属持久层
  • 和数据库交互(执行者)

@Component(组件)

  • 归属于公共工具类
  • 提供某些公共方法

@Configuration(配置)

  • 归属于配置层
  • 用来配置当前项目的一些信息(对项目的全局配置负责)

实例理解

  • 创建一个 StudentController 类,并使用 @Controller 注解将其注入到 Spring 容器中
  • 将该实例的 @Controller 注解换成 @Service、@Repository、@Component、@Configuration 均可实现将当前类注入到 Spring 容器中
package com.java.demo;

import org.springframework.stereotype.Controller;

// 使用 @Controller 注解将当前类存储到 spring 容器中
@Controller
public class StudentController {
    public void sayHi() {
        System.out.println("student controller say hi");
    }
}
  • 在启动类中获取 Bean 对象,并使用 Bean 对象
import com.java.demo.StudentController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
//        得到 Spring 上下文对象
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
//        获取 Bean 对象
        StudentController studentController = context.getBean("studentController",StudentController.class);
        studentController.sayHi();
    }
}
  • 此处我们并未在配置文件中使用 Bean 标签将 StudentController 对象注入到 Spring 容器中
  • 而是直接使用 @Controller 注解将其注入到 Spring 容器
  • 所以当我们要使用 getBean 方法获取该 Bean 对象的时候,其默认 id 为原类名的小驼峰形式

运行结果:

注意:

  • 此处的 Bean 对象的 id 命名还存在特殊情况 
  • 创建一个 SController 类
import org.springframework.stereotype.Controller;

@Controller
public class SController {
    public void sayHi() {
        System.out.println("s controller say hi");
    }
}
  • 在启动类中获取 Bean 对象,并使用 Bean 对象
import com.java.demo.SController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
//        得到 Spring 上下文对象
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
//        获取 Bean 对象
        SController sController = context.getBean("sController",SController.class);
        sController.sayHi();
    }
}

运行结果:

结论1:

  • 默认情况 Bean 对象 id 为原类名的小驼峰形式
  • 但如果类名的第一个字母和第二个字母都是大写,则其 Bean 对象 id 应为 原类名

五大类注解 Bean 对象 id 命名规则原码


结论2:

  • 在配置文件中,<content:component-scan> 标签和 <bean> 标签可以同时使用
  • <bean> 标签可补充注入 不在扫描路径中的 Bean 对象

实例理解

  • 创建一个 UserService 类
public class UserService {
    public void sayHi() {
        System.out.println("user service say hi");
    }
}
  • 使用 <bean> 标签将 UserService 类的 Bean 对象注入到 Spring容器中

  • 在启动类中获取 Bean 对象并使用
import com.java.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
//        得到 Spring 上下文对象
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
//        获取 Bean 对象
        UserService userService = context.getBean("userService",UserService.class);
        userService.sayHi();
    }
}

运行结果:


结论3:

  • 不在 <component-scan> 中所设置的扫描路径下 且被五大类注解标识的类,不会注入到 Spring 容器中

结论4:

  • 在 <component-scan> 中所设置的扫描路径下 但未被五大类注解标识的类,不会注入到 Spring 容器中

结论5:

  • 在  <component-scan> 中所设置的扫描路径下的所有子包的类,只要加了五大类注解的类,会注入到 Spring 容器中

使用方法注解 @Bean

  •  相比较于五大类注解 添加到某个类上
  • 方法注解 @Bean ,顾名思义就是将其添加到方法上的

注意:

@Bean 注解 必须要配合 五大类注解一起使用

  • 只有加了 五大类注解的类,Spring 才会 扫描该类
  • 进而才会扫描当前类中的方法是否有加了 @Bean 注解的
  • 这是出于 Spring 性能设计所规定的策略

@Bean 注解 Bean 对象命名规则:

  • 默认情况下,@Bean 存储的 Bean 对象的 id 就是方法名

实例理解

  • 我们创建一个 实例类 User
// 普通的用户实体类
public class User {
    public Integer uid;
    public String username;
    public String password;
    public Integer age;

    public Integer getUid() {
        return uid;
    }

    public void setUid(Integer uid) {
        this.uid = uid;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}
  • 我们再创建一个 UserBeans 类
  • 在该类中写一个方法,来创建 实例类 User 的对象
  • 并使用 @Bean 注解将 User 的 Bean对象 注入到 Spring 容器中
  • 注意此处搭配了五大类注解中的 @Component 注解
import com.java.demo.entity.User;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@Component
public class UserBeans {
    @Bean
    public User user1() {
        User user = new User();
        user.setUid(1);
        user.setUsername("张三");
        user.setPassword("123456");
        user.setAge(18);
        return user;
    }
}
  • 在启动类中获取该 Bean 对象
  • 注意此处获取 Bean 对象时的 id 为 user1,即被 @Bean 注解所修饰方法的方法名
import com.java.demo.entity.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
//        得到 Spring 上下文对象
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
//        获取 Bean 对象
        User user = context.getBean("user1",User.class);
        System.out.println(user.getUsername());
    }
}

运行结果:


重命名 Bean 

  • 默认情况下,@Bean 存储的 Bean 对象的 id 就是方法名
  • 但是我们还是可以自己手动设置 Bean 对象的 id

实例理解

  • 我们可以通过下图方式给 Bean 对象设置多个 id

  • 在启动类中获取该 Bean 对象
  • 此时我们任选一个 id 即可获取该 Bean 对象,此处选择 id 为 u1
import com.java.demo.entity.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
//        得到 Spring 上下文对象
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
//        获取 Bean 对象
        User user = context.getBean("u1",User.class);
        System.out.println(user.getUsername());
    }
}

运行结果:

注意:

  • 当给 Bean 对象重命名之后,默认的使用方法名获取对象的方式就不能再使用了

补充问题

  • 我们创建一个 UserBeans 类,且未重命名 Bean 对象
import com.java.demo.entity.User;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@Component
public class UserBeans {
    @Bean
    public User getUser() {
        User user = new User();
        user.setUid(1);
        user.setUsername("张三");
        user.setPassword("123456");
        user.setAge(18);
        return user;
    }
}
  • 我们再创建一个 UserBeans2 类,且未重命名 Bean 对象
import com.java.demo.entity.User;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@Component
public class UserBeans2 {
    @Bean
    public User getUser() {
        User user = new User();
        user.setUid(2);
        user.setUsername("李四");
        user.setPassword("123456");
        user.setAge(20);
        return user;
    }
}
  • 在启动类中获取该 Bean 对象
import com.java.demo.entity.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
//        得到 Spring 上下文对象
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
//        获取 Bean 对象
        User user = context.getBean("getUser",User.class);
        System.out.println(user.getUsername());
    }
}

运行结果:

  • 我们多次运行启动类,发现所获取到始终是 Username 为李四的 Bean 对象
  • 但是 Username 为张三的 Bean 对象,其 id 也为 getUser,但是为什么获取的不是它呢?
  • 此处涉及到数据覆盖
  • 因为 Username 为张三 且 id 为 getUser 的 Bean 对象,先被注入到 Spring 容器中
  • 此时 Username 为李四 且 id 为 getUser 的 Bean 对象,再被注入到 Spring 容器中
  • 正因为 Spring 容器中已经又了 id 为 getUser 的 Bean 对象,所以后注入到的 Username 为李四 的 Bean 对象 便将 Username 为张三 的 Bean 对象 给覆盖了
  • 所以此处启动类获取到的 Bean 对象其 Username 输出为 李四

我们可以通过 @Oder 注解来更清晰的观察该情况

  • @Oder 注解 是用来控制 Bean 对象注入顺序
  • 其参数值越小,其权重就越大,也就越先被注入到 Spring 容器中

类注解之间的关系

注意:

  • @Controller、@Service、@Repository、@Configuration 均是针对 @Component 的一个扩展
  • 这几个注解均能将当前类注入到 Spring 容器中,其功能基本一致
  • 之所以分这么多类注解,其原因就是:
  • 能让程序员看到注解之后便知道当前类的作用

上述类注解对应着 JavaEE 标准分层(至少三层)

  1. 控制层
  2. 服务层
  3. 数据持久层
  • 当一个类不合适放在上面三层中的任意一个时,可用 @Component 注解进行分层的扩展和补充

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

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

相关文章

树莓派在Raspbian系统(Bookworm)中无法获取RJ45网口eth0或end0的IP地址(没有IPv4的地址无法操作)

由于 Raspbian 上个月刚好从 Bullseye 升级到 Bookworm 版本了&#xff0c;所以出现了很多修改&#xff0c;截止写博客的时候过去还没三十天&#xff0c;当然也没那么多解决方案参考&#xff0c;只能参考之前版本或者靠自己了&#xff0c;未来或许官方会进行修复&#xff0c;也…

飞桨平台搭建PP-YOLOE模型

一、创建项目 此博客仅是运行PP-YOLOE源码&#xff0c;这里以变压器渗漏数据集为例COCO数据集太大了&#xff0c;跑不动&#xff0c;V100训练预估计得7天左右&#xff0c;即便是A100也得4天半&#xff0c;变压器渗漏油数据集跑一个小时左右&#xff0c;还可以接受&#xff0c;…

vue3生命周期源码详解

钩子函数的特点 Vue 生命周期钩子函数是在组件生命周期中执行的特定函数。 这些钩子函数允许你在组件不同的生命周期阶段插入自定义的逻辑代码。 Vue 提供了一组预定义的生命周期钩子函数&#xff0c;每个钩子函数在组件生命周期的不同阶段被调用。 源码中如何注册、实现钩子函…

cad绘图模板建立

都设置好后保存为文件&#xff0c;收藏好&#xff0c;下次打开即可使用设置好的样式&#xff0c;完成后另存为新的文件名即可 1.f7关闭格栅 2.ds草图设置 3.图纸不能缩小&#xff1a;格式——图形界限—— 4.un单位设置 5.标注样式设置&#xff1a;d 完成后置为当前 6. st…

docker存储卷

docker存储卷 COW机制 Docker镜像由多个只读层叠加而成&#xff0c;启动容器时&#xff0c;Docker会加载只读镜像层并在镜像栈顶部添加一个读写层。 如果运行中的容器修改了现有的一个已经存在的 文件&#xff0c;那么该文件将会从读写层下面的只读层复制到读写层&#xff0…

5米DEM高程数据分析和对比

数字高程模型&#xff08;DEM&#xff09;是应用最广泛的地理信息数据之一&#xff0c;是进行三维空间处理和地形分析的数据基础。每个行业数据精度要求不一样&#xff0c;很多行业使用公开免费的90米和30米分辨率DEM就够了。而城市规划、交通线路规划、地质灾害防控、城区地籍…

【QT】 Qt自定义ui控件

在使用Qt的ui设计时&#xff0c;Qt为我们提供了标准的窗口控件&#xff0c;但是在很多复杂工程中&#xff0c;标准窗口控件并不能满足所有的需求&#xff0c;这时就需要我们自定义控件。我们自定义的类既可以作为独立的窗口显示&#xff0c;又可以作为一个控件显示。 我们要实现…

Spring相关

SpringBoot自动装配 阿里云登录 - 欢迎登录阿里云&#xff0c;安全稳定的云计算服务平台 Spring相关 阿里云登录 - 欢迎登录阿里云&#xff0c;安全稳定的云计算服务平台 常用设计模式 双亲委派 Java虚拟机定义了三个主要的类加载器: 1、启动类加载器 2、扩展类加载器 …

python教程:打印心型图案 九九乘法表 三角形 金字塔 圣诞树 倒三角形 菱形

# 打印九九乘法口诀表 for i in range(1, 10): # 乘法表的行、起始值从1开始for j in range(1, i 1): # 表示每一行的表达式、从1开始、到j1print({}*{}{}.format(j, i, i * j), end ) # 输出语句{}占位、输出表达式print( )# 打印金字塔&#xff08;正三角形&#xff09; …

web3 dapp React项目引入 antd 对 balance 用户token信息组件进行样式改造

好 上文 web3 React dapp中编写balance组件从redux取出并展示用户资产 我们简单处理了用户资产的展示 那么 我们继续 先启动 ganache 环境 终端输入 ganache -d然后 打开我们的项目 将合约发布到区块链上 truffle migrate --reset然后 我们启动项目 确认一切正常 还原到上文…

wangeditor富文本编辑器的使用(vue)

官网 官方demo 参考 安装 yarn add wangeditor/editor yarn add wangeditor/editor-for-vue 封装的富文本组件 <template><div style"border: 1px solid #ccc"><Toolbarstyle"border-bottom: 1px solid #ccc":editor"editorRef"…

P02项目(学习)

★ P02项目 项目描述&#xff1a;安全操作项目旨在提高医疗设备的安全性&#xff0c;特别是在医生离开操作屏幕时&#xff0c;以减少非授权人员的误操作风险。为实现这一目标&#xff0c;我们采用多层次的保护措施&#xff0c;包括人脸识别、姿势检测以及二维码识别等技术。这些…

工程压缩与解压缩

很多工程师在完成一个电气工程后&#xff0c;会遇到一些问题&#xff0c;例如&#xff1a;在SOLIDWORKSElectrical 中如何把做好的工程发送给别的工程师&#xff0c;或者更换了电脑如何把旧电脑的工程转移到新电脑 上&#xff1b;有时候&#xff0c;工程师也有可能会遇到解压工…

Redis概述和安装

&#x1f388;个人公众号:&#x1f388; :✨✨✨ 可为编程✨ &#x1f35f;&#x1f35f; &#x1f511;个人信条:&#x1f511; 知足知不足 有为有不为 为与不为皆为可为&#x1f335; &#x1f349;本篇简介:&#x1f349; 本篇详细阐述了Redis概述和安装&#xff0c;如有出入…

经典OJ题:找环节点——代码解析

题目&#xff1a; 给定一个链表的头节点 head &#xff0c;返回链表开始入环的第一个节点。 如果链表无环&#xff0c;则返回 null。如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测…

【每日一题】统计范围内的元音字符串数

文章目录 Tag题目来源题目解读解题思路方法一&#xff1a;遍历 其他语言python3 写在最后 Tag 【遍历】【数组】【2023-11-07】 题目来源 2586. 统计范围内的元音字符串数 题目解读 统计范围内的元音字符串数。 解题思路 方法一&#xff1a;遍历 遍历下标在 [left, right]…

用循环结构程序自动化计算——计数循环

用循环结构程序自动化计算——计数循环 低阶目标&#xff1a; 利用for循环结构来完成已知次数的自动化处理&#xff0c;掌握计数循环结构应用方法 高阶目标&#xff1a; 学会利用for循环解决生活中的实际问题 用循环结构程序自动化计算——计数循环 用循环结构程序自动化计算…

Leetcode48旋转图像

思路&#xff1a;找规律 方法一、一般辅助数组解法 行列转换&#xff0c;第一行变到第三列&#xff0c;第二行变到第二列&#xff0c;第三行变到第一列 matrix[row][col] matrix[col][n-row-1] 然后复制回原数组 class Solution {public void rotate(int[][] matrix) {in…

第十二章 Python正则表达式

系列文章目录 第一章 Python 基础知识 第二章 python 字符串处理 第三章 python 数据类型 第四章 python 运算符与流程控制 第五章 python 文件操作 第六章 python 函数 第七章 python 常用内建函数 第八章 python 类(面向对象编程) 第九章 python 异常处理 第十章 python 自定…

独立键盘接口设计(Keil+Proteus)

前言 软件的操作参考这篇博客。 LED数码管的静态显示与动态显示&#xff08;KeilProteus&#xff09;-CSDN博客https://blog.csdn.net/weixin_64066303/article/details/134101256?spm1001.2014.3001.5501实验&#xff1a;用4个独立按键控制8个LED指示灯。 按下k1键&#x…