Spring(三): 使用注解来存储和读取Bean对象

news2024/11/20 10:35:08

目录

  • 一、存储Bean对象
    • 1.1 配置扫描路径
    • 1.2 使用注解存储Bean对象
    • 1.3 通过上下文读取Bean对象
    • 1.4 Bean命名规则
    • 1.5 方法注解 @Bean
    • 1.5 重命名Bean
  • 二、获取Bean对象
    • 2.1 属性注入
    • 2.2 Setter注入
    • 2.3 构造方法注入
    • 2.4 Resource注解
    • 2.5 Resource注解中name参数的作用

一、存储Bean对象

在 Spring 中想要更简单的存储和读取对象的核心是使用注解

1.1 配置扫描路径

想要将Bean对象存储到Spring中,需要配置存储对象的扫描包路径,只有被配置的包下所有类,添加了注解才能被正确识别并保存到Spring中

在spring.xml添加配置:

<?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 htt
p://www.springframework.org/schema/beans/spring-beans.xsd http://www.spring
framework.org/schema/context https://www.springframework.org/schema/contex
t/spring-context.xsd">
    <content:component-scan base-package="com.bit"></content:component-scan>
</beans>

在这里插入图片描述

【为什么要在spring的配置文件中,配置扫描路径?】

如果你作为Spring的设计者,如果不要求使用者配置扫描路径,Spring就应该扫描全部类,这样的效率很低

1.2 使用注解存储Bean对象

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

  1. 类注解:
  • @Controller:控制器,验证前端传递的参数,起到类似于"安检"的作用
  • @Service:服务,服务调用的编排和汇总(安排服务的执行顺序和对服务进行汇总,但并不真正的操作数据),例如前端某个页面提供一个修改头像的功能,这个功能由两步组成(替换头像图片和增加用户积分),服务层的功能是安排这两个服务的执行先后顺序
  • @Repository:仓库,直接操作数据库,操作用户的保存头像图片的表和积分表
  • @Component:组件,修饰一些工具类,这些工具类与业务无关
  • @Configuration:配置,项目的所有配置
  1. 方法注解:@Bean

【程序的工程分层,调用流程】

在这里插入图片描述

下面使用的是Controller注解,其他注解都是类似的

package com.bit;
import org.springframework.stereotype.Controller;
@Controller
public class User {
    public  void method(){
        System.out.println("hello User");
    }
}

1.3 通过上下文读取Bean对象

import com.bit.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import javax.jws.soap.SOAPBinding;

public class App {
    public static void main(String[] args) {

        //参数中传的是spring的配置文件名称
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");

        User user=applicationContext.getBean("user",User.class);//默认的id名为小驼峰(并不绝对,后面详细说)
        user.method();
    }
}

1.4 Bean命名规则

我们先看下面这两个示例
(1)
在这里插入图片描述
(2)当要注册的类名的前两个首字母都是大写字母时,如果在获取时依然使用首字母小写作为id来获取就会报错

在这里插入图片描述

【观察默认bean命名规则的源代码】

(1)在这里插入图片描述
(2)在这里插入图片描述
(3) 观察发现,当类名首字母大写第二个字母小写时默认的beanName是首字母小写,当类名首字母和第二个字母都大写时默认的beanName和类名相同
在这里插入图片描述

1.5 方法注解 @Bean

类注解是添加到某个类上的,而方法注解是放到某个方法上的,如以下代码的实现
在这里插入图片描述
当我们写完以上代码,尝试获取 bean 对象中的 user1 时却发现,根本获取不到:
在这里插入图片描述
这是因为在Spring框架中,方法注解Bean要配合类注解才能将对象正常的存储到Spring容器中

修改代码:
在这里插入图片描述
通过Bean注解注册对象的默认beanName是方法名,因此我们通过方法名来获取注册到Spring当中的User对象
在这里插入图片描述

1.5 重命名Bean

重命名Bean主要用来解决:在两个不同类中有两个同名的方法且返回的对象类型相同且这两个方法都被Bean注解修饰,此时我们在根据方法名取对象时只能取到其中的一个
在这里插入图片描述
对Bean重命名:

StudentBeans

package com.bit;

import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@Component
public class StudentBeans {
    @Bean(name = "studentbeans_user")
    //@Bean("studentbeans_user") 效果一样
    //@Bean(name = {"studentbeans_user","user1","user2"})起多个名字
    public  User user(){
        User user=new User();
        user.setName("lisi");
        user.setId(100);
        return  user;
    }
}

UserBeans

package com.bit;

import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;

@Controller
public class UserBeans {
    @Bean(name = "userbeans_user")
    public  User user(){
        User user=new User();
        user.setName("zhangsan");
        user.setId(100);
        return  user;
    }
}

按照重命名后的名字取Bean
在这里插入图片描述
【注意】

  • 必须和5大类注解一起使用
  • Bean注解不能修饰带有参数的方法,因为该参数没有办法传
  • 重命名之后,不能再通过方法名来获取Bean了

在这里插入图片描述

二、获取Bean对象

获取Bean对象也叫做对象装配,是把对象取出来放到某个类中,有时候也叫对象注入。
对象装配的实现方法有以下三种:

  1. 属性注入
  2. 构造方法注入
  3. Setter注入

2.1 属性注入

属性注入是使用@Autowired实现的
下面演示在UserController中注入UserService对象
UserService:

package com.bit;

import org.springframework.stereotype.Service;

@Service
public class UserService {
    /**
     * 根据 ID 获取⽤户数据
     *
     * @param id
     * @return
     */
    public User getUser(Integer id) {
        // 伪代码,不连接数据库
        User user = new User();
        user.setId(id);
        user.setName("Java-" + id);
        return user;
    }
}

UserController:

package com.bit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class UserController {
    @Autowired
    private UserService userService;
    public  User getUser(Integer id){

        return userService.getUser(id);
    }
}

App:

public class App {
    @Autowired
    private  UserController userController;
    public static void main(String[] args) {

        //参数中传的是spring的配置文件名称
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");

      UserController userController=applicationContext.getBean("userController",UserController.class);
        System.out.println(userController.getUser(1));
    }
}

【注意】

不能在静态方法中使用通过Autowired注入的对象,因为Spring自动注入的时机比静态方法执行的时机晚
在这里插入图片描述

【优缺点分析】

优点:使用简单
缺点:

  • 无法注入一个不可变的对象(final 修饰的对象) 在这里插入图片描述
  • 只能适应于IoC容器
  • 更容易违背单一设计原则(指某个类只干一件事,不能既干这又干那)

2.2 Setter注入

UserController类:


@Controller
public class UserController {
    private  UserService userService;
    @Autowired  //Setter注入的方式
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
    public  User getUser(Integer id){
        return userService.getUser(id);
    }
}

UserService的写法同上

【优缺点分析】

优点:符合单一设计原则(一个Setter只针对一个对象)
缺点:

  • 不能注入一个final对象
  • Setter注入对象可能会被改变,因为set方法可能被多次调用
    在这里插入图片描述

2.3 构造方法注入

UserController类


@Controller
public class UserController {

    private  UserService userService;
       @Autowired
    public UserController(UserService userService){
        this.userService= userService;
    }
    public  User getUser(Integer id){
        return userService.getUser(id);
    }
}

【注意】

  • 如果只有一个构造方法,@Autowired注解可以省略
  • 如果类中有多个构造方法,那么需要添加上 @Autowired 来明确指定到底使用哪个构造方法,否则程序会报错
  • 可以在一个构造方法中注入多个对象
    在这里插入图片描述
    在这里插入图片描述
  • 一个类中只能使用Autowired注解修饰一个构造方法(仔细一想,因为在Java规范中,创建一个对象时,即使类中有多个构造方法,也只会执行其中的某一个)
    在这里插入图片描述

【优点】

  • 可以注入final修饰的对象
  • 注入的对象不会被修改,构造方法在对象创建时只会执行一次,因此不存在注入对象被修改的情况
  • 完全初始化,因为依赖对象是在构造方法中执行的,而构造方法是在对象创建之初执行的,因此被注入的对象在使用之前,会被完全初始化
  • 通用性更好,因为构造方法是Java支持的【最底层的框架】,所以更换任何的框架都是支持的

2.4 Resource注解

在进行依赖注入时,除了可以使用Autowired注解,JDK也提供了一个Resource注解,可以达到同样的效果

属性注入的方式:

@Controller
public class UserController {
    @Resource
    private  UserService userService;
    public  void doUserController(){
        userService.doUserService();

    }
}

Setter注入的方式:


@Controller
public class UserController {

    private  UserService userService;

    @Resource
    public  void setUserService(UserService userService){
        this.userService=userService;
    }
    public  void doUserController(){
        userService.doUserService();

    }
}

Resource注解不支持构造方法注入
在这里插入图片描述

【@Autowired和@Resource的区别】

  • @Autowired来自于Spring,@Resource来自于JDK
  • @Autowired 可用于 Setter 注入、构造函数注入和属性注入,而@Resource只能用于 Setter 注入和属性注入,不能用于构造函数注入
  • 相比于 @Autowired 来说,@Resource 支持更多的参数设置,例如 name 设置,根据名称获取 Bean。 在这里插入图片描述

2.5 Resource注解中name参数的作用

当在一个类中有两个方法,返回的对象类型相同且这两个方法都被Bean修饰,在另一个类中获取该对象时就会报错,具体看下面示例

UserBeans类中,有user1和user2方法,都返回User对象且被Bean注解修饰

@Controller
public class UserBeans {
    @Bean
    public  User user1(){
        User user=new User();
        user.setName("zhangsan");
        user.setId(100);
        return  user;
    }
    
    @Bean
    public  User user2(){
        User user=new User();
        user.setName("lisi");
        user.setId(200);
        return  user;
    }
}

在UserController类中通过Autowired属性注入的方式注入User对象

@Controller
public class UserController {
    @Autowired
     private  User user;
    public  User getUser(){
        return  user;
    }
}

App类启动时程序报错(使用Resource注解也会报同样的错误)
在这里插入图片描述
【发生上述错误的原因和注解的匹配方式有关】

  • 对于Autowired注解来说,先根据类型匹配,如果匹配到多个对象,再使用name进行筛选,如果筛选后仍有多个对象,则会报错
  • 对于Autowired注解来说,先根据name匹配,如果匹配到多个对象,在使用类型进行筛选,如果筛选后仍有多个对象,则会报错
  • 在上述例子中,类型和name分别是: 在这里插入图片描述

【解决方式】

  1. 在使用注解注入时将变量名user改为user1或user2,这样就可以通过name筛选得到唯一对象
  2. 在不改变user的情况下,可以使用Resource中的name注解指定要获取的对象name
    在这里插入图片描述
    在这里插入图片描述
  3. 使用Autowired+Qualifier,在Qualifier注解的value参数中指定name,根据这个name进行筛选
    在这里插入图片描述

【补充】

Spring存储Bean的方式类似于HashMap,
key为对象的默认命名或类型,value为对应的对象
在这里插入图片描述

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

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

相关文章

说明书丨艾美捷Annexin-V-Cy3凋亡检测试剂盒

Cy3标记的重组人膜联蛋白V显示亮红色荧光&#xff08;Ex&#xff08;max&#xff09;:543nm&#xff1b;Em&#xff08;最大值&#xff09;&#xff1a;570nm&#xff09;。 艾美捷Annexin-V-Cy3凋亡检测试剂盒化学性质&#xff1a; Applications: Flow Cytometry, Fluorescen…

C++【修理之路】初识string

这里写目录标题为什么学习string类&#xff1f;标准库中的string类string的定义转换为C风格的字符串string类的输出和输出访问字符串中的字符字符串的拼接string 字符串的增删改查总结为什么学习string类&#xff1f; C语言中&#xff0c;字符串是以’\0’结尾的一些字符的集合…

3D数学之四元数 学习笔记

四元数有三个虚部&#xff0c;一个实部 [ w (x y z) ] w xi yj zk i j k ijk -1 用于表示&#xff0c;物体在空间中的任意角度旋转 四元数的模 Sqrt(pow(w, 2) pow(x, 2) pow(y, 2) pow(z, 2)) 四元数共轭&#xff1a;p a bi 共轭为&#xff1a; p a - bi …

一文梳理 | 电力企业网络安全管理及等级保护工作重点

前言 为加强电力行业网络安全监督管理&#xff0c;规范电力行业网络安全工作&#xff0c;国家能源局近日印发《电力行业网络安全管理办法》和《电力行业网络安全等级保护管理办法》&#xff08;以下简称“两办法”&#xff09;&#xff0c;有效期均为5年。随着这两部规范性文件…

门神 马丁内斯 要什么样的成就,才不枉这些年的颠沛流离

2022-12-18日 随着劳塔罗的最后一球波网而入 阿根廷成功获得了卡塔尔世界杯的冠军 结束后 所有人都去拥抱劳塔罗 只有梅西拉起了倒在地上的马丁内斯 很多人说 在这次比赛中 阿根廷有两个神 一个是球王梅西 另一个则是 门将 马丁内斯 当场上二比零时 所有人都以为阿根廷胜券在…

(二)汇编语言——寄存器

目录 通用寄存器 汇编指令 物理地址 接下来我们来介绍寄存器&#xff0c;同时会介绍一些基本的语句&#xff08;mov,add等)&#xff0c;好了&#xff0c;就让我们进入今天的学习吧&#xff01;同时&#xff0c;我们以8086为例子来介绍&#xff0c;参考来自王爽老师的书。 说…

JAVA架构与开发(从0开始搭建一个springCloud web项目)

从0开始搭建一个springCloud web项目。 一、首先需要的开发工具&#xff1a; 1、SpringToolSuite4 &#xff0c;个人目前用的最熟练的JAVA开发工具。 2、JDK1.8&#xff0c;按照网上安装jdk的步骤安装就行。 3、maven-3.6.1 4、springBoot官网 Spring Boot 5、配置中心 Apo…

架构师必读 —— 逻辑模型(14)

从"is/is not" "before / after”的角度思考 遇到问题时&#xff0c;为了研究“为什么会发生这种问题”&#xff0c;可以将问题发生之前和发生后做一个对比&#xff0c;这样效果会更明显。通过明确差距&#xff08;差异&#xff09;&#xff0c;可以比较"在…

前端学习-创建vue项目

1.下载vscode windows系统安装第一个 linux系统安装第二个 苹果系统安装第三个 vscode 官网下载地址 下载地址&#xff1a;https://code.visualstudio.com/Download 2.下载git 选择对应的系统下载&#xff0c;跟随官网提示操作 下载地址&#xff1a;https://git-scm.com/down…

C++多线程编程基础

1.创建线程Thread 首先要引入头文件#include&#xff0c;管理线程的函数和类在该头文件中声明&#xff0c;其中包括std::thread类。 语句"std::thread th1(proc1);"创建了一个名为th1的线程&#xff0c;并且线程th1开始执行。 实例化std::thread类对象时&#xff…

你知道什么是 @Component 注解的派生性吗?

对于 Component 注解在日常的工作中相信很多小伙伴都会使用到&#xff0c;作为一种 Spring 容器托管的通用模式组件&#xff0c;任何被 Component 注解标注的组件都会被 Spring 容器扫描。 那么有的小伙伴就要问了&#xff0c;很多时候我们并没有直接写 Component 注解呀&…

计算机毕设Python+Vue寻人系统设计(程序+LW+部署)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Spring Boot日志文件

哈喽呀&#xff0c;你好呀&#xff0c;欢迎呀&#xff0c;快来看一下这篇宝藏博客吧~~~ 目录 1.日志快速扫盲 2.Spring Boot项目日志简单分析 3.自定义打印日志 4.通过设置日志的级别来筛选和控制日志输出的内容 5.日志持久化 1.日志快速扫盲 什么是日志?说白了就是控制…

Java学习笔记——Idea集成git

Idea集成git-创建本地仓库-提交代码

深入浅出pom.xml文件

前言 在每一个pom文件的开头都会有这样几行代码 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocatio…

Spring Boot3.0正式发布及新特性解读

Spring Boot 3.0 正式发布 同时发布更新的还有 2.7.x 和 2.6.x 两条版本线&#xff0c;Spring Boot 是我见过的发版最守时的技术框架之一。 Spring Boot 3.0 现已正式发布&#xff0c;它包含了 12 个月以来 151 个开发者的 5700 多次代码提交。这是自 4.5 年前发布 2.0 以来&a…

Live800:在线客服系统排名是怎么样的?

在线客服系统排名是怎么样的?在线客服系统提供商提供哪些服务?在线客服系统评测要点?这些都是企业很关心的问题,这里进行简要的解答。 在线客服系统排名是怎么样的? 客观来说在线客服系统没有统一的行业标准,因此也没有统一的排名。各在线客服系统厂商各有特色,行业竞争激…

【大数据】python连接并使用redis

文章目录redis安装redis连接python安装redis库conda下载及配置vs连接redisredis使用stringset设置getrange截取append追加内容strlen(key) 字节长度listlpush,rpush赋值lpushx,rpushx只给存在的键值赋值llen 列表个数linsert 在某一个值前或者后插入新值lset 对某一个索引位置赋…

Hive 源码解读 准备篇 Debug 讲解

使用 Hive 执行 HQL 查询时遇到 bug,解决办法无非几种,explain HQL、查看日志、远程 Debug,本文就将详细讲解如何使用 Idea 远程 Debug。 1. Debug 环境准备 下载 Hive 源码包,自行编译一下,建议在 Linux 环境下编译,然后将整个编译好的包全部拷贝到 IDEA 工作目录中并…

软考高级-系统架构设计师-知识点总结(一)架构设计基础

第一部分&#xff0c;架构设计基础。由系统架构设计师概述、计算机与网络基础知识、信息系统基础知识、系统开发基础知识四部分构成。 目录 系统架构设计师概述 系统架构的概念和历史 系统架构设计师的定义 系统架构师具备的能力 计算机与网络基础知识 操作系统基础 操作…