【SpringⅡ】简单高效地存储读取对象

news2024/12/23 18:36:40

目录

🧥1 配置扫描路径

🧤2 类注解实现 Bean 对象的存储

🩱2.1 五大类注解的使用

🎁2.2 五大类注解之间的关系

🎏2.3 Java 项目的标准分层

🎃3 方法注解实现 Bean 对象的存储

🎈3.1 Bean 注解必须配合五大类注解一起使用

✨3.2 重命名 @Bean 的几种方式

🎁4 依赖注入


在上一篇的文章的最后(Spring 的创建与使用),我介绍了往 Spring 里存储 Bean 的方式:在 spring_config 中添加一行 bean 注册内容如下:

采用这种写法的话,每一个类都必须在 spring-config 里写上这么一行。然而有另一种更加便捷的方式,可以在 spring-config 里只添加一行,便可以存储且获取同一路径下的所有对象。

1 配置扫描路径

与上述写法不同的是,不再使用 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">
    <content:component-scan base-package="com.java.demo"></content:component-scan>
</beans>

配置 bean 的扫描路径意味着,只有当前目录下的类才会扫描是否添加了注解。如果添加了注解,就将这些添加了注解的类存放到 IoC 容器中。

下面介绍两种更加简单存储 Bean 对象的方式

2 类注解实现 Bean 对象的存储

五大类注解:

1. @Controller【控制器】校验参数的合法性(安检系统)

2. @Service【服务】业务组装(客服中心)

3. @Repository【数据持久层】实际业务处理(实际办理的业务)

4. @Component【组件】工具类层(基础的工具)

5. @Configuration【配置层】配置

2.1 五大类注解的使用

package com.java.demo;

import org.springframework.stereotype.Controller;

@Controller
public class User {
    public void sayHi(){
        System.out.println("Hi User~");
    }
}
package com.java.demo;

import org.springframework.stereotype.Service;

@Service
public class Student {
    public void sayHi(){
        System.out.println("Hi! Student!");
    }
}
package com.java.demo;

import org.springframework.stereotype.Repository;

@Repository
public class ABCdefH {
    public void sayHi(){
        System.out.println("Hi! ABCdefH!");
    }
}
package com.java.demo;

import org.springframework.stereotype.Component;

@Component
public class TEacher {
    public void sayHi(){
        System.out.println("Hi! TEacher!");
    }
}
package com.java.demo;

import org.springframework.context.annotation.Configuration;

@Configuration
public class Hello {
    public void sayHi(){
        System.out.println("Hello! !");
    }
}
import com.java.demo.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        User user = context.getBean("user", User.class);
        user.sayHi();
        TEacher teacher = context.getBean("TEacher", TEacher.class);
        teacher.sayHi();
        ABCdefH abcdefh = context.getBean("ABCdefH", ABCdefH.class);
        abcdefh.sayHi();
        Hello hello = context.getBean("hello", Hello.class);
        hello.sayHi();
        Student student = context.getBean("student", Student.class);
        student.sayHi();
    }
}

输出:

Hi User~
Hi! TEacher!
Hi! ABCdefH!
Hello! !
Hi! Student!

类注解存储 Bean 命名时,有一个默认的命名规则:

如果首字母大写,第二个字母小写,那么 Bean 的名称就是类名小写:如上的 User、Student 以及 Hello 类。但如果不满足上述情况,那么 Bean 的名称就为原类名,如上述的 TEacher 以及 ABCdefH 类。

来看一下 Bean 生成名称的源代码:

public static String decapitalize(String name) {
        if (name == null || name.length() == 0) {
            return 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);
    }

可以看到,五类注解方法功能上都是一样的,但为什么要分出五类来呢?为了后续代码的分层管理。

2.2 五大类注解之间的关系

依次点开五大类注解的源代码:

 

可以看出其他四类都是基于 Component 的,所以以后实在不知道用哪个注解比较好的话,就使用 Component 吧~

2.3 Java 项目的标准分层

 

3 方法注解实现 Bean 对象的存储

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

一起来看怎么样使用吧!

首先给定一个文章的实体类来:

package com.java.demo;

import java.time.LocalDateTime;

/*
* 普通的文章实体类
 */
public class ArticlesInfo {
    private int id;
    private String title;
    private String content;
    private LocalDateTime time;

    @Override
    public String toString() {
        return "ArticlesInfo{" +
                "id=" + id +
                ", title='" + title + '\'' +
                ", content='" + content + '\'' +
                ", time=" + time +
                '}';
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public void setTime(LocalDateTime time) {
        this.time = time;
    }

    public int getId() {
        return id;
    }

    public String getTitle() {
        return title;
    }

    public String getContent() {
        return content;
    }

    public LocalDateTime getTime() {
        return time;
    }
}

创建文章:

package com.java.demo;

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

import java.time.LocalDateTime;

@Controller
public class Articles {

    @Bean
    public ArticlesInfo articlesInfo(){
        // 伪代码
        ArticlesInfo articlesInfo = new ArticlesInfo();
        articlesInfo.setId(1);
        articlesInfo.setTitle("Know yourself");
        articlesInfo.setContent("Keep Learning ~");
        articlesInfo.setTime(LocalDateTime.now());
        sayHi();
        return articlesInfo;
    }
    
    public void sayHi(){
        System.out.println("Hi~~~");
    }
}
import com.java.demo.Articles;
import com.java.demo.ArticlesInfo;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        ArticlesInfo articles = context.getBean("articlesInfo", ArticlesInfo.class);
        System.out.println(articles.toString());
    }
}

输出:

ArticlesInfo{id=1, title='Know yourself', content='Keep Learning ~', time=2023-07-19T15:29:30.731}

需要注意的是,本身的类也会被存储到 Spring 中:

        Articles articles1 = context.getBean("articles", Articles.class);
        articles1.articlesInfo();

输出:

Hi~~~

可以发现,使用 Bean 对方法进行注解时,@Bean 的默认命名是方法名。

3.2 重命名 @Bean 的几种方式

@Bean("aaa")
@Bean(name = "bbb")
@Bean(value = "ccc")

@Bean 支持指定多个名称

@Bean(value = {"aaa", "bbb"})

需要注意的是,当 @Bean 重命名之后,默认使用方法名获取 Bean 对象的方式就不能用了。

另一个要注意的是,如果多个 Bean 使用相同的名称,程序执行不会报错。除了第一次使用某一 Bean 名称的方法之外(根据加载顺序),后面使用相同 Bean 名称的方法,都不会被存放到容器当中,会被自动忽略。

4 依赖注入

依赖注入与依赖查找的对比

· 依赖查找依靠 Bean 名称来进行查找

· @Autowired 依赖注入流程:首先根据 getType(从容器中)获取对象,如果只获取一个,    那么直接将此对象注入到当前属性上;如果获取多个对象,就会使用 getName(根据名        称)来进行匹配。

 

package com.java.demo;

import org.springframework.stereotype.Repository;

@Repository
public class UserRepository {
    public int add(){
        System.out.println("Do UserRepository add method");
        return 1;
    }
}

 

package com.java.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    // Spring 2.0 使用属性注入的方式
    @Autowired  // DI (依赖注入)
    private UserRepository userRepository;

    public int add(){
        System.out.println("Do UserService add method.");

        // 1.传统写法
//        UserRepository userRepository = new UserRepository();
//        return userRepository.add();

        // 2. Spring 1.0
//        ApplicationContext context =
//                new ClassPathXmlApplicationContext("spring-config.xml");
//        UserRepository userRepository = context.getBean("userRepository", UserRepository.class);
//        return userRepository.add();

        //

        // 3. Spring 2.0
        return userRepository.add();


    }
}

对着需要测试的类,右击,点击 Generate,再点 Test 生成一个测试类。通过测试类来进行测试。

package com.java.demo;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import static org.junit.jupiter.api.Assertions.*;

class UserServiceTest {

    @org.junit.jupiter.api.Test
    void add() {
        ApplicationContext context = 
                new ClassPathXmlApplicationContext("spring-config.xml");
        UserService userService = context.getBean("userService", UserService.class);
        userService.add();
    }
}

 输出:

Do UserService add method.
Do UserRepository add method

可以看到使用属性注入,代码更加简洁了。

如果是下面这种情况,会出现什么问题呢?

package com.java.demo;

public class User {
    private String name;

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
package com.java.demo;

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

@Component
public class Users {
    @Bean("user1")
    public User user1(){
        User user = new User();
        user.setName("马冬梅");
        return user;
    }

    @Bean("user2")
    public User user2(){
        User user = new User();
        user.setName("王五");
        return user;
    }
}

同类型的 Bean 放入了同一个 Spring 当中,如果是 属性注入,该如何获取呢?

采用下面两种方式:

1. 将属性的名字与 Bean 的名字一一对应,是 user1 还是 user2,而不是写成的 user。


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

@Service
public class UserService2 {
    // 属性注入
    @Autowired
    private User user1;

    public void sayHi(){
        System.out.println(user1.toString());
    }
}

2. @Autowired 配合 @Qualifier 一起使用

package com.java.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

@Service
public class UserService2 {
    // 属性注入
    @Autowired
    @Qualifier("user1")
    private User user;

    public void sayHi(){
        System.out.println(user.toString());
    }
}
package com.java.demo;

import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import static org.junit.jupiter.api.Assertions.*;

class UserService2Test {

    @Test
    void sayHi() {
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        UserService2 user = context.getBean("userService2",UserService2.class);
        user.sayHi();
    }
}

 


 

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

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

相关文章

❤️创意网页:HTML5 Canvas技术实现绚丽多彩的烟花特效

✨博主&#xff1a;命运之光 &#x1f338;专栏&#xff1a;Python星辰秘典 &#x1f433;专栏&#xff1a;web开发&#xff08;简单好用又好看&#xff09; ❤️专栏&#xff1a;Java经典程序设计 ☀️博主的其他文章&#xff1a;点击进入博主的主页 前言&#xff1a;欢迎踏入…

node中的数据持久化之mysql

一、数据库的基本概念 1. 什么是数据库 数据库&#xff08;Database&#xff09;是按照数据结构来组织、存储和管理数据的仓库。每个数据库都有一个或多个不同的API用于创建、访问、管理、搜索和复制所保存的数据。我们也可以将数据存储在其他地方&#xff0c;例如&#xff1…

XML加密和数字签名

上篇文章我们了解了常用的Java加密库和算法,这篇文章主要讲解Java解密在XML中的使用。 XML加密 XML加密(XML Encryption)是指对XML文档中的敏感数据进行加密,以确保只有授权的用户能够解密和访问这些数据。XML加密使用对称或非对称加密算法,对敏感数据进行加密,并将加…

237. 删除链表中的节点

题目描述&#xff1a; 主要思路&#xff1a; 将当前要删除的节点和后边一个的节点值交换&#xff0c;然后删除当前节点后边的一个节点即可。 class Solution { public:void deleteNode(ListNode* node) {node->valnode->next->val;node->nextnode->next->n…

分享一个唯美雪花界面

先看效果&#xff1a; 再看代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>雪</title><meta name"viewport" content"widthdevice-width, initial-scale1&…

linux开机启动输入法且设置英文状态

debian&#xff0c;gnome桌面。fcitx5框架&#xff0c;四叶草输入法。 首先把fcitx5加到开机启动项&#xff0c;方法很多&#xff0c;gnome的插件“优化”里面可以添加开机启动项。 这样开机就能启动输入法&#xff0c;而不用再手动输入shell命令fcitx5了。 但是启动时是中…

vue-element-admin解决跨域问题

更改vue.config.js publicPath: process.env.NODE_ENV production ? /tyzfadmin : /,//开发和生产环境不一样&#xff0c;做个判断 outputDir: dist, assetsDir: static, lintOnSave: false, runtimeCompiler: true, productionSourceMap: false, devServer: {port: port,op…

瑞芯微|如何让拥有双网口的Linux设备实现数据包转发?

本文主要讲解如何&#xff0c;解决基于3568实现双网口互通问题。 一、组网 如下图所示&#xff1a; rk3568自带2个千兆以太口&#xff0c;对应网卡名称为&#xff1a;eth0、eth1pc1和pc2分别连接这2个网口pc1与eth0连接&#xff0c;网段&#xff1a;192.168.30.0pc2与eth1连…

途乐证券-新型城镇概念拉升,东方园林涨停,蕾奥规划等大涨

新型乡镇概念19日盘中发力走高&#xff0c;到发稿&#xff0c;蕾奥规划涨近13%&#xff0c;东方园林涨停&#xff0c;顾地科技涨超8%&#xff0c;新城市、艾布鲁、启迪环境等涨超5%。 消息面上&#xff0c;在国新办18日举行的国务院方针例行吹风会上&#xff0c;住建部房地产市…

django rest_framework 框架动态设置序列化返回的字段

动态修改字段可以使Django rest框架API像graphQL端点一样&#xff0c;只从模型中检索所需的字段。 一旦序列化器被初始化&#xff0c;就可以使用.fields属性访问序列化器上设置的字段字典。访问和修改此属性允许您动态修改序列化器。 显式地修改fields参数可以帮助您做一些奇…

解码 LangChain|用 LangChain 和 Milvus 从零搭建 LLM 应用

如何从零搭建一个 LLM 应用&#xff1f;不妨试试 LangChain Milvus 的组合拳。 作为开发 LLM 应用的框架&#xff0c;LangChain 内部不仅包含诸多模块&#xff0c;而且支持外部集成&#xff1b;Milvus 同样可以支持诸多 LLM 集成&#xff0c;二者结合除了可以轻松搭建一个 LLM…

猿辅导推出颠覆性产品小猿学练机,加速个性化学习时代到来

近期&#xff0c;沉默近两年的猿辅导在智能硬件领域释放动作&#xff0c;发布旗下首款智能硬件产品——小猿学练机。这一动作代表着&#xff0c;猿辅导正式入局1000亿智能硬件市场。据了解&#xff0c;小猿学练机面向全国中小学生&#xff0c;主打学练一体、以练促学&#xff0…

外部邻区TAC配置错误导致语音被叫无响应问题分析

1、问题描述 用户131********用户&#xff08;中兴AXON 40终端&#xff09;容易出现被叫无响应的现象&#xff0c;现场测试发生概率大约10%。 2、信令分析 6月4日现场测试时&#xff0c;11.47分左右&#xff0c;131********测试时出现一起未接通问题。 端到端平台信令回溯分析…

ubuntu - Linux 下的常用命令

ls 查看当前文件夹下的内容 pwd 查看当前所在文件夹 cd 切换文件夹 touch 如果文件不存在&#xff0c;创建文件 mkdir 创建新目录 rm 删除指定的文件 clear 清屏 ctrl shift 放大终端窗口的字体显示 ctrl - 缩小终端窗口的字体显示 按 上&#xff0f;下 光标键可以在…

【硕士论文完美复现】【价格型需求响应】基于需求侧响应的配电网供电能力综合评估(Matlab代码实现)

目录 &#x1f4a5;1 概述 1.1 电价伸缩系数分析 1.2 需求侧响应数学模型 1.3 粒子群算法求解 1.4 本文流程图 &#x1f4da;2 运行结果 2.1 风电和光伏的出力情况 2.2 峰谷时段分类 2.3 分时电价制定及负荷响应结果 2.3.1 仅考虑需求响应 2.3.2 考虑分布式和需…

图论 并查集 模拟 位运算—题841、127、684、685、657、31、463、1356 C++实现与有向图 无向图 并查集总结

文章目录 841.钥匙和房间DFSBFS 127. 单词接龙684.冗余连接685.冗余连接II657. 机器人能否返回原点31.下一个排列463. 岛屿的周长解法1解法2 1356. 根据数字二进制下 1 的数目排序解法1解法2 注意点 图论&#xff1a;题841、127 并查集&#xff1a;题684、685 模拟&#xff1a;…

记一次从溯源分析到云服务器接管

起因是我这个臭运维的在给客户做常态化的溯源分析&#xff0c;好巧不巧发现了一个IP扔到奇安信威胁情报平台看一下&#xff0c;发现部署了大量的服务&#xff0c;且为阿里云服务器。 看到这里&#xff0c;我大胆的推测&#xff0c;云上的信息中心&#xff0c;客户花点钱&#x…

《教育界》期刊简介及投稿邮箱

《教育界》期刊简介及投稿邮箱 一、《教育界》期刊简介 《教育界》是面向各级教育行政主管部门、教育科研院所、各类大中专院校、中小学校及其从事教育教学工作的教育工作者和专业教师的综合性教育教学类素质教育专业性教育学术理论期刊。 主管单位&#xff1a;广西师范大学…

create database创建数据库失败

瀚高数据库 目录 环境 症状 问题原因 解决方案 环境 系统平台&#xff1a;Linux x86-64 Red Hat Enterprise Linux 7 版本&#xff1a;4.5.7 症状 1、执行如下sql语句创建数据库报错。 create database printcdburn with encodingUTF8 OWNERprintcdburn LC_COLLATEzh_CN.UTF-…

蓝桥杯真题:密码脱落(区间dp)

目录 题目&#xff1a; 解题思路&#xff1a; dp分析&#xff1a; 解题代码&#xff1a; 题目&#xff1a; 解题思路&#xff1a; 题目要求的为脱落的种子数&#xff08;即回文字符中没有对应回文的字符的数量&#xff09; 我们可以转换成求回文字符串最长回文字符串的长…