【Spring】Spring更简单的读取和存储对象---使用注解

目录

1.Spring的存储对象------存储Bean对象

1.前置工作,配置扫描路径

2.添加注解存储Bean对象

1.@Controller(控制器存储)

2.@service(服务存储)

3.@Repository(仓库存储)

4.@Component(组件存储)

5.@Configuration(配置存储)

3.为什么这么多类注解

1.类注解之间的关系

4.方法注解@Bean

1.方法注解要搭配类注解使用

2.重命名Bean

2.Spring的读取------获取Bean对象(对象装配)

1.属性注入

2.构造方法注入

3.Setter注入

4.三种注入方法的优缺点

 5.@Resource:另一种注入关键字

@Resource和@Autowired的区别

6.同一类型多个@Bean报错

1.现象

 2.报错处理

使⽤ @Resource(name="xxx")

使⽤ @Qualifier


在上一篇文章中实现了基本的Spring读取和存储对象。但在操作的过程中我们发现读取和存储对象并没有想象中的那么“简单”。

所以接下来我们要讲解更加简单的操作 Bean 对象的⽅法。其核心就是,使用注解

1.Spring的存储对象------存储Bean对象

之前我们存储 Bean 时,需要在 spring-config 中添加⼀⾏ bean 注册内容才⾏,如下图所示:

⽽现在我们只需要⼀个注解就可以替代之前要写⼀⾏配置的尴尬了。

类注解规则:1.类名前两位均为大写时,返回自身name

                  2.否则,首字母小写

1.前置工作,配置扫描路径

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

在spring-config.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 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>

其中标红的一行为注册扫描的包,如下图所示:

注意:即使添加了注解,如果不是在配置的扫描包下的类对象,也是不能被存储到Spring中的。

2.添加注解存储Bean对象

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

1. 类注解:@Controller、@Service、@Repository、@Component、@Configuration。

2. ⽅法注解:@Bean。

1.@Controller(控制器存储)

使用@Controller存储Bean的代码如下所示:

@Controller
public class UserController {
    public void sayHi(){
        System.out.println("hi,userController~");
    }
}

在App中读取上面的UserController对象:

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

运行结果:

这里并没有在spring-config.xml中添加id,但是依旧能正确运行。是因为@Controller注解自动的起到了一个id的作用。作用与如下代码一致:

    <bean id="userController" class="org.example.UserController"></bean>

2.@service(服务存储)

使用@service存储Bean的代码如下所示:

@Service
public class UserService {
    public void doService(){
        System.out.println("doService");
    }
}

在App中读取上面的UserService对象:

public class App {
    public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
        UserService userService=(UserService) context.getBean("userService");
        userService.doService();
    }
}

3.@Repository(仓库存储)

使用@Repository存储Bean的代码如下所示:

@Repository
public class UserRepository {
    public void sayHi(){
        System.out.println("hi,repository");
    }
}

在App中读取上面的UserRepository对象:

public class App {
    public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
        UserRepository userRepository=(UserRepository) context.getBean("userRepository");
        userRepository.sayHi();
    }
}

4.@Component(组件存储)

使用@Component存储Bean的代码如下所示:

@Component
public class UserComponent {
    public void sayHi(){
        System.out.println("hi,component");
    }
}

在App中读取上面的UserComponent对象:

public class App {
    public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
        UserComponent userComponent=(UserComponent) context.getBean("userComponent");
        userComponent.sayHi();
    }
}

5.@Configuration(配置存储)

使用@Configuration存储Bean的代码如下所示:

@Configuration
public class UserConfiguration {
    public void doConfiguration(){
        System.out.println("hi,Configuration");
    }
}

在App中读取上面的UserConfiguration对象:

public class App {
    public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
        UserConfiguration userConfiguration=(UserConfiguration) context.getBean("userConfiguration");
        userConfiguration.doConfiguration();
    }
}

3.为什么这么多类注解

由以上对每个注解的介绍,可以看出,这些注解的功能都是一样的,那么为什么需要这么多类注解呢?

其目的就是让程序员看到类注解之后,就能直接了解当前类的用途。

@Controller:表示业务逻辑层,通常是指程序的入口,比如:参数校验,参数类型转换等前置处理工作。

@Service:服务层,一般写业务代码,服务编排,比如:调用DB,调用第三方接口。

@Repository:持久层,仓库,通常指DB操作相关的代码。(通常放在DAO层下面)

@Component:其它的对象。

@Configuration:配置层。

程序的工程分层,调用流程如下:

1.类注解之间的关系

查看 @Controller / @Service / @Repository / @Configuration 等注解的源码发现:

 其实这些注解⾥⾯都有⼀个注解 @Component,说明它们本身就是属于 @Component 的“子类”。

4.方法注解@Bean

1.方法注解要搭配类注解使用

在 Spring 框架的设计中,⽅法注解 @Bean 要配合类注解才能将对象正常的存储到 Spring 容器中,如下代码所示:

@Configuration
public class BeanConfig {
    @Bean
    public User user() {
        User user=new User();
        user.setName("温温");
        user.setAge(18);
        return user;
    }
}

注意:@Bean对应生产的bean名称是方法名

2.重命名Bean

可以通过设置name属性给Bean对象进行重命名操作,如下对象所示:

@Configuration
public class BeanConfig {
    @Bean(name={"wen","user"})
    public User user() {
        User user=new User();
        user.setName("温温");
        user.setAge(18);
        return user;
    }
}

此时使用wen和user都可以获取到User对象了:

        User user=(User) context.getBean("wen");
        System.out.println(user.getName());

2.Spring的读取------获取Bean对象(对象装配)

获取 bean 对象也叫做对象装配,是把对象取出来放到某个类中,有时候也叫对象注⼊

对象装配(对象注⼊)的实现⽅法以下 3 种:

1. 属性注⼊

2. 构造⽅法注⼊

3. Setter 注⼊

1.属性注入

属性注⼊是使⽤ @Autowired 实现的,将 Service 类注⼊到 Controller 类中。

Service类的代码如下:

@Service
public class UserService {
    public void doService(){
        System.out.println("doService");
    }
}

Controller类的实现代码如下:

@Controller
public class UserController {
    @Autowired
    private UserService userService;
    public void sayHi(){
        userService.doService();
        System.out.println("hi,userController~");
    }
}

最终结果如下:

2.构造方法注入

构造方法注入是在类的构造方法中实现注入,实现代码如下:

@Controller
public class UserController2 {
    private UserService us;
    public UserController2(UserService us) {
        this.us = us;
    }
    public void sayHi(){
        us.doService();
        System.out.println("hi,userController~");
    }
}

注意:1.如果只有一个构造方法,那么@Autowired可以省略

           2.如果有多个构造方法,那么需要添加上@Autowired来明确指定到底使用哪个构造方法,否则程序会报错。

3.Setter注入

Setter 注⼊和属性的 Setter ⽅法实现类似,只不过在设置 set ⽅法的时候需要加上 @Autowired 注

解,如下代码所示:

@Controller
public class UserController1 {
    private UserService us;
    @Autowired
    public void setUs(UserService us) {
        this.us = us;
    }
    public void sayHi(){
        us.doService();
        System.out.println("hi,userController~");
    }
}

4.三种注入方法的优缺点

优点缺点
属性注入简介,使用方便
1.是只能⽤于 IoC 容器,如果是⾮ IoC 容器不可⽤,并且只有在使⽤的时候才会出现 NPE(空指针异常)
2.不能注入一个final修饰的属性
构造方法注入(
 Spring 推荐

1.可以注入final修饰的属性

2.注入的对象不会被修改

3.依赖对象在使用前一定会被完全初始化

4.通用性好

如果有多个注⼊会显得⽐较臃肿,但出现这种情况你应该考虑⼀下当前类是否符合程序的单⼀职责的设计模式了,
setter注入
方便再类实例之后,重新对该对象进行配置或注入
1.不能注入一个final修饰的属性
2.注入对象可能会被改变,因为setter方法可能会被多次调用,就有被修改的风险

补充:final修饰的属性,需要具备下列两个条件之一:

1.初始化赋值

2.构造函数赋值

 5.@Resource:另一种注入关键字

在进⾏类注⼊时,除了可以使⽤ @Autowired 关键字之外,我们还可以使⽤ @Resource 进⾏注⼊,如下代码所示:

@Controller
public class UserController3 {
    @Resource
    private UserService us;

    public void sayHi(){
        us.doService();
        System.out.println("hi,userController~");
    }
}

@Resource和@Autowired的区别

  • 出身不同:@Autowired来自于Spring,⽽ @Resource 来⾃于 JDK 的注解;
  • 使⽤时设置的参数不同:相⽐于 @Autowired 来说,@Resource ⽀持更多的参数设置,例如 name 设置,根据名称获取 Bean。
  • @Autowired 可⽤于 Setter 注⼊、构造函数注⼊和属性注⼊,⽽ @Resource 只能⽤于 Setter 注⼊和属性注⼊,不能⽤于构造函数注⼊。

补充:

@Autowired

根据类型来获取bean,如果同一个类型的bean只有一个,直接注入成功

如果同一个类型的bean有多个,以名称匹配,注入相同名称的bean

如果没有名称相同的,就报错

6.同一类型多个@Bean报错

1.现象

当出现以下多个 Bean,返回同⼀对象类型时程序会报错,如下代码所示:

@Component
public class Users {
 @Bean
 public User user1() {
 User user = new User();
 user.setId(1);
 user.setName("Java");
 return user;
 }
 @Bean
 public User user2() {
 User user = new User();
 user.setId(2);
 user.setName("MySQL");
 return user;
 }
}

在另一个类中获取User对象:

@Controller
public class UserController4 {
 // 注⼊
 @Resource
 private User user;
 public User getUser() {
 return user;
 }
}

报错了,报错原因为:非唯一的Bean对象

 2.报错处理

解决同⼀个类型,多个 bean 的解决⽅案有以下两个:

  • 使⽤ @Resource(name="user1") 定义。
  • 使⽤ @Qualifier 注解定义名称。

使⽤ @Resource(name="xxx")

使⽤ @Qualifier

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

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

相关文章

Java面试突击

Java面向对象有哪些特征&#xff0c;如何应用 ​ 面向对象编程是利用类和对象编程的一种思想。万物可归类&#xff0c;类是对于世界事物的高度抽象 &#xff0c;不同的事物之间有不同的关系 &#xff0c;一个类自身与外界的封装关系&#xff0c;一个父类和子类的继承关系&…

手动下载composer项目放在vendor目录下并加载

比如添加easywechat。 说是手动&#xff0c;其实半手动。 到GitHub或gitee下载 1、下载后放在项目根目录下的vendor文件夹 2、在项目根目录的文件composer.json文件添加一段 "autoload": {"psr-4": {"EasyWeChat\\": "vendor/overtrue/wech…

HCIP第一课实验小练习

目录 题目&#xff1a;​编辑 第一步&#xff1a;地址规划&#xff08;子网划分&#xff09; 第二步&#xff1a;设计拓扑并规划地址配置 第三步&#xff1a;VLAN规划配置 LW1 LW2 第四步&#xff1a;网关配置 第五步&#xff1a;及静态路由配置 第六步防止成环 题目&…

计算机视觉和滤帧技术

01 什么是计算机视觉 进入主题之前&#xff0c;先聊聊计算机视觉。 计算机视觉是指利用摄像头和电脑识别、跟踪和测量目标&#xff0c;并进行图像处理&#xff0c;使其适合人眼观察或仪器检测。作为一个科学学科&#xff0c;计算机视觉模拟生物视觉&#xff0c;旨在实现图像和视…

郭东白的架构课学习笔笔记(1)

1.架构师的品质 自信和勇气&#xff08;正确的废话&#xff09;拥有战略意图&#xff0c;所谓战略意图&#xff0c;就是拥有与其资源和能力极不相称的雄心壮志。使用演绎法寻找架构原理&#xff0c;而不是归纳法。 2.如何提升自己的架构能力 向身边比自己厉害的优秀架构师或…

【yarn】 ‘husky install‘ fails if ‘.git‘ directory does not exists解决方法

问题描述 环境&#xff1a;win10 yarn 1.22.19 问题&#xff1a;在使用yarn安装前端依赖时&#xff0c;yarn install 出现错误: .git can’t be found (see https://git.io/Jc3F9) error Command failed with exit code 1. 截图 原因分析 根据设计&#xff0c;husky安装必…

scala学习手册

1. case class学习 样例类模式匹配 1.1 样例类&#xff08;case class&#xff09;适合用于不可变的数据。它是一种特殊的类&#xff0c;能够被优化以用于模式匹配。 case class MetaData(userId: String)case class Book(name: String) {def printBookName(): Unit {printl…

Python读取excle文件,插入到数据库

一、需求背景 最近项目实践过程中遇到了一个问题&#xff1a;在使用Navicat将数据导入到PostgreSQL数据库时&#xff0c;发现时间格式的字段中的时间数值发生了变化&#xff0c;导致部分数据的时间不正确&#xff0c;故数据手动导入数据库报错。为了解决这个问题&#xff0c;决…

ARM中栈的种类与运用

1. 栈的概念 栈&#xff0c;本身是一段内存&#xff0c;程序运行时用于保存一些临时数据&#xff0c;如局部变量、参数、返回地址等等。 学习了数据结构&#xff0c;对栈的概念相信大家都不陌生&#xff0c;后进先出的数据结构&#xff0c;即最后进栈的元素最先出栈。但是在C语…

(学习笔记-TCP基础知识)TCP与UDP区别

UDP UDP不提供复杂的控制机制&#xff0c;利用IP提供面向[无连接]的通信服务。 UDP协议非常简单&#xff0c;头部只有8个字节(位)&#xff0c;UDP的头部格式如下&#xff1a; 目标和源端口&#xff1a;主要是告诉UDP协议应该把报文发给哪个进程包长度&#xff1a;该字段保存了…

【码银送书第二期】《高并发架构实战:从需求分析到系统设计》

很多软件工程师的职业规划是成为架构师&#xff0c;但是要成为架构师很多时候要求先有架构设计经验&#xff0c;而不做架构师又怎么会有架构设计经验呢&#xff1f;那么要如何获得架构设计经验呢&#xff1f; 一方面可以通过工作来学习&#xff0c;观察所在团队的架构师是如何…

栈和队列【数据结构】

1、栈 &#xff08;1&#xff09;Stack.h #pragma once #include <stdio.h> #include <assert.h> #include <stdlib.h> #include <stdbool.h>typedef int STDataType;typedef struct Stack {STDataType* a;int top;int capacity; }ST;void STInit(ST*…

设计模式——桥梁模式

桥梁模式 定义 桥梁模式&#xff08;Bridge Pattern&#xff09;也叫做桥接模式。 将抽象和显示解耦&#xff0c;使得两者可以独立地变化。 优缺点、应用场景 优点 抽象和实现的解耦。 这是桥梁模式的主要特点&#xff0c;它完全是为了解决继承的缺点而提出的设计模式。优…

声音生成项目(6)——在矢量量化变分编码器上使用自回归模型PixelCNN模型生成新的样本

文章目录 引言PixelCNN论文简读模型介绍自回归模型PixelCNN模型结构 基础知识回顾 代码实现PixelConvLayer具体运行过程卷积模块整体网络结构 模型执行效果问题解决训练好的模型在生成新的图片时&#xff0c;为什么要逐个元素进行生成&#xff1f;掩码卷积仅仅是考虑了一部分的…

R语言实现SMOTE与SMOGN算法解决不平衡数据的回归问题

本文介绍基于R语言中的UBL包&#xff0c;读取.csv格式的Excel表格文件&#xff0c;实现SMOTE算法与SMOGN算法&#xff0c;对机器学习、深度学习回归中&#xff0c;训练数据集不平衡的情况加以解决的具体方法。 在之前的文章Python实现SMOGN算法解决不平衡数据的回归问题&#x…

Spring初识(二)

前言 经过前面的学习,我们已经知道spring就是包含了众多方法的Ioc,那么既然是容器,就具备两个功能,我们接下来就是要介绍以下两个功能: 1.将对象存储到容器(spring)中: 2.从容器(spring)中将对象取出来. 这两个功能就应发出来,spring的创建和使用. 一.Spring创建 我们先来说…

Ubuntu关闭自动休眠

一、查看当前休眠模式 使用systemctl status sleep.target 命令查看当前休眠模式&#xff0c;结果如下图&#xff0c;sleep状态为enabled&#xff0c;表示自动休眠模式开启。 二、关闭自动休眠模式 使用sudo systemctl mask sleep.target suspend.target 关闭休眠模式 三…

面向初学者的卷积神经网络

卷积神经网络在机器学习中非常重要。如果你想做计算机视觉或图像识别任务&#xff0c;你根本离不开它们。但是很难理解它们是如何工作的。 在这篇文章中&#xff0c;我们将讨论卷积神经网络背后的机制、它的优点和应用领域。 什么是神经网络&#xff1f; 首先&#xff0c;让…

【ACM】—蓝桥杯大一暑期集训Day2

&#x1f680;欢迎来到本文&#x1f680; &#x1f349;个人简介&#xff1a;陈童学哦&#xff0c;目前正在学习C/C、Java、算法等方向&#xff0c;一个正在慢慢前行的普通人。 &#x1f3c0;系列专栏&#xff1a;陈童学的日记 &#x1f4a1;其他专栏&#xff1a;CSTL&#xff…

MySQL-分库分表详解(二)

♥️作者&#xff1a;小刘在C站 ♥️个人主页&#xff1a; 小刘主页 ♥️努力不一定有回报&#xff0c;但一定会有收获加油&#xff01;一起努力&#xff0c;共赴美好人生&#xff01; ♥️学习两年总结出的运维经验&#xff0c;以及思科模拟器全套网络实验教程。专栏&#xf…