Spring更简单读取和存储对象

news2024/11/25 10:47:06

目录

前言

注解

存储Bean

通过类注解

配置扫描路径

添加类注解存储Bean对象

@Controller(控制器存储)

@Service(服务存储)

 @Repository(仓库存储)

 @Component(组件存储)

 @Configuration(配置存储)

 类注解之间的关系

Bean的命名规则

通过方法注解

重命名Bean

方式一

方式二

方式三

方式四

获取Bean(对象装配)

属性注入

属性注入的优缺点

Setter注入

Setter注入优缺点

构造方法注入

构造方法优点


前言

上篇文章介绍了spring的创建和基本的存储、读取对象的方式,但是在操作过程中我们发现过程其实是很麻烦的,所以接下来我们将学习更加简单的读取和存储对象的方式。

注解

在Spring框架中,注解是一种用于配置和管理应用程序组件的特殊标记,通过使用注解,可以简化配置和开发过程,使整体代码更加的清晰,易读和易于维护。

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

存储Bean

通过类注解

其实当我们在学习JavaEE这块的时候,我们的思想首先应该转变一下,回忆之前的代码,很多时候我们都是自己写功能,自己写实现方式,其实在spring部分,我们想要实现一个功能,我们首先应该想到有没有对应实现该功能的注解。

我们在之前进行Bean的存储时,需要在spring-config.xml这个文件中添加一个bean标签用于注册Bean才行。

这是之前我们的写法,如果有多个Bean对象需要存储时,此时就很麻烦了,就需要一个Bean写一个bean标签了,而现在我们只需要一个注解就可以解决之前的尴尬了。

配置扫描路径

想要将对象存储到spring容器中去,我们就需要配置一下存储对象的扫描包路径,只有在我们配置了扫描包路径下面的类,添加了注解之后,才会正确的存储到spring容器中去。

和之前创建spring的方式一致,我们需要有spring-config.xml这个配置文件。

在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="com.java.domo">

    </content:component-scan>
</beans>

也就是说,只有在这个路径下,同时使用了注解才能被spring存储。

添加类注解存储Bean对象

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

  • 类注解 @Controller、@Service、@Repository、@Component、@Configuration
  • 方法注解 @Bean

@Controller(控制器存储)

使用@Controller注解存储Bean对象:

@Controller
public class UserController {
    public void sayHi() {
        System.out.println("hello Controller");
    }
}

然后我们在通过之前获取对象的方式来读取上面的UserController对象。

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

可以看到对象是成功的获取到了,并且成功的调用了里面的方法。

@Service(服务存储)

使用@Service注解存储Bean对象:

@Service
public class UserService {
    public void sayHi(String name) {
        System.out.println("name=" + name);
    }
}

读取Bean:


public class Application {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("Spring-config.xml");
        UserService userService = context.getBean("userService", UserService.class);
        userService.sayHi("hello");
    }
}

 @Repository(仓库存储)

使用@Repository注解存储Bean对象:

@Repository
public class UserRepository {
    public void sayHi(String name) {
        System.out.println("name="+ name);
    }

}

获取Bean:

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

 @Component(组件存储)

使用@Component注解存储Bean对象:

@Component
public class User01 {
    public void sayHi(String name) {
        System.out.println("name="+name);
    }
}

获取Bean:

public class Application {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("Spring-config.xml");
        User01 user01 = context.getBean("user01", User01.class);
        user01.sayHi("Component");
    }
}

 @Configuration(配置存储)

使用@Configuration存储Bean对象:

@Configuration
public class UserConfiguration {
    public void sayHi(String name) {
        System.out.println("name="+name);
    }
}

获取Bean:

public class Application {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("Spring-config.xml");
        UserConfiguration userConfiguration = context.getBean("userConfiguration", UserConfiguration.class);
        userConfiguration.sayHi("Component");
    }
}

 类注解之间的关系

从上述的代码可以看出来的是,上述的5大类注解的功能是一样。

既然功能是一样,但是还是有5个,不是一个,这是因为当程序员看到了当前类注解之后,就能快速的明白当前类的主要用途。

比如:

@Controller 使用了这个注解的类表示的是业务逻辑层

@Service  使用这个类注解的类表示的服务层

@Repository 使用了这个类注解的类表示数据持久层

@Component  使用了这个类注解的类表示工具类层

@Configuration  使用了这个类注解的类表示配置层

这里我们需要知道程序整体之间的调用逻辑:

 

 5个类注解之间关系则是继承关系:

可以看到 @Controller、@Service、@Repository、@Configuration则是全部继承与@Component。

Bean的命名规则

上述代码我们可以看出,通常我们Bean使用的都是大驼峰命名,而读取的时候则是首字符小写的方式读取。如下图:

 如果我们把获取Bean时的名称不按照上述名称的方式进行读取时,就会出现错误。

我们接下来就可以看看Spring存储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);
    }

我们可以看到当第一个字符和第二字符都是大写的情况下,就是把bean也是按照首字符大写的方式存储了,第二个字符也是大写。

如果不是第一个和第二个都是大写的情况下,就是安装首字符小写的方式进行存储了。

通过方法注解

类注解是添加到某个类上的,而方式注解则是添加到某个方法上的。

需要注意的是,这些类都是在我们前面在spring-config.xml配置文件中配置的扫描包路径下的。

User类:

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;
    }
}

Users类:在Users类中通过方法注解获取User对象。 

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

将User对象返回并打印信息:

public class Application {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("Spring-config.xml");
        User user = context.getBean("user1", User.class);
        System.out.println(user.toString());
    }
}

 上述代码我们可以看出,方法注解是配合类注解一起使用的。如果没有配合类注解的话,是不能正确的存储和获取bean对象的。

从上述代码我们可以看到,在获取Bean时的命名是和方法名一致的。也就是说在获取bean时的默认命名则是方法名。

重命名Bean

方式一

可以通过@Bean注解中直接赋值的方式给对象进行重命名的操作:

@Component
public class Users {
    @Bean("u1")
    public User user1() {
        User user = new User();
        user.setName("张三");
        return user;
    }
}

此时我们就可以使用u1来获取User对象了:

public class Application {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("Spring-config.xml");
        User user = context.getBean("u1", User.class);
        System.out.println(user.toString());
    }
}

方式二

可以通过@Bean注解中的name属性给Bean对象进行重命名操作:

@Component
public class Users {
    @Bean("u2")
    public User user1() {
        User user = new User();
        user.setName("张三");
        return user;
    }
}
public class Application {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("Spring-config.xml");
        User user = context.getBean("u2", User.class);
        System.out.println(user.toString());
    }
}

方式三

通过@Bean注解中的value属性给Bean对象进行重命名操作:

@Component
public class Users {
    @Bean(value = "u3")
    public User user1() {
        User user = new User();
        user.setName("张三");
        return user;
    }
}
public class Application {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("Spring-config.xml");
        User user = context.getBean("u3", User.class);
        System.out.println(user.toString());
    }
}

方式四

通过重命名扩展的方式给Bean设置名称:

@Component
public class Users {
    @Bean(value={"u4","u5","u6"})
    public User user1() {
        User user = new User();
        user.setName("张三");
        return user;
    }
}

通过上述的这种方式设置名称后,就可以通过任意一个名称进行Bean对象的获取了。

注意:在@Bean重命名后,那么默认的根据方法名获取Bean对象的方式就不能使用了。

 

获取Bean(对象装配)

获取Bean对象也叫对象装配,是把某个对象取出来放在某个类中,也称为对象注入。

对象装配(对象注入)的方式有3种:

  • 属性输入
  • Setter注入
  • 构造方法注入

属性注入

属性注入是通过@Autowired注解实现的。

下面我们按照实际开发的方式进行注入:

 整个项目结构。

我们在UserRepository里面假设将获取数据库中的数据,并封装了一个方法进行查询数据库操作。然后将查询到的数据库放入User对象中,进行返回。

然后在UserService里面通过属性注入的方式注入,再调用UserRepository里面的获取数据库的方法。

然后在UserController里面将UserService通过属性注入的方式注入,再调用UserService里面的方法。

整体流程是UserController——>UserService——>UserRepository(进行数据库查询,返回对象)。

UserRepository类具体实现:


@Repository
public class UserRepository {

    public User getUser() {
        //伪代码   具体业务的实现
        User user = new User();
        user.setId(1);
        user.setName("张三");
        return user;
    }
}

UserService类具体实现:


@Service
public class UserService {

    @Autowired   //通过注解的方式将对象注入到这里
    private UserRepository userRepository;
 
    public User getUser() {    //在通过注入的对象进行业务的实现
        return userRepository.getUser();
    }
}

UserController类具体实现:

@Controller
public class UserController {

    @Autowired   //通过属性注入的方式将UserService注入
    private UserService userService;

    public User getUser() {  //在通过注入的对象进行业务的实现
        return userService.getUser();
    }
}

可以看到比之前下面这种获取对象的方式更加方便了。

// Spring V1.0      依赖查找
        ApplicationContext context = new ClassPathXmlApplicationContext("Spring-config.xml");
        UserRepository userRepository = context.getBean("userRepository",UserRepository.class);
        return userRepository.getUser();

 

执行代码能成功的获取到从数据库返回的对象。

属性注入也称为依赖注入,我们之前用到的获取Bean对象的方式是属于依赖查找。

依赖注入VS依赖查找:

依赖查找时根据Bean名称的

依赖注入则是先根据类型从容器中获取对象,如果只能获取一个,那么就直接将此对象注入到当前属性上,如果获取到多个对象,才会使用名称进行匹配。

属性注入的优缺点

优点:使用简单

缺点:

  • 无法注入通过final修饰的变量
  • 只适用于IoC容器
  • 更容易违背单一设计原则,因为使用起来简单,更容易注入其他类型的对象

Setter注入

Setter注入和属性Set方法实现类似,只不过在设置Set方法时需要添加上@Autowired注解。

@Controller
public class UserController {

    //Setter注入
    private UserService userService;

    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }


    /*@Autowired  属性注入
    private UserService userService;*/

    public User getUser() {
        return userService.getUser();
    }
}

Setter注入优缺点

优点:完全符合单一设计原则,因为setter注入每次都只能设置一个对象。

缺点:

  • 不能注入final修饰的不可变对象
  • 注入的对象可以被随时修改

因为final修饰的属性只能在定义的时候进行初始化,或者在构造方法中进行初始化。

注入的对象可以被修改是因为提供了setXXX方法,意味着我随时可以调用这个方法来改变注入对象。

构造方法注入

构造方法注入是在类的构造方法中进行注入:


@Controller
public class UserController {
    
    //构造方法注入
    private UserService userService;
    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }

  /*  //Setter注入
    private UserService userService;
    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }*/


    /*@Autowired  属性注入
    private UserService userService;*/
    public User getUser() {
        return userService.getUser();
    }
}

注意:如果一个类中只有一个构造方法,那么不加@Autowired注解也是可以的,但是如果多个构造方法,就需要加上注解,用来表示到底使用那个构造方法进行注入。

构造方法优点

  • 可以注入不可变对象,也就是final修饰的对象,因为final修饰的属性只能在初始化或者构造方法中赋值。
  • 注入的对象不会被修改,因为构造方法只执行一次。
  • 注入的对象会完成被初始化,因为在对象创建之前,被注入的对象会被完成的初始化,在进行注入。
  • 通用性更好,可以适用于非IoC的框架。

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

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

相关文章

【【51单片机 --秒表--定时器扫描按键数码管】】

轻松做秒表&#xff0c;谁用谁知道 我们在Key 和Nixie 内部都写一个函数这个是main 中中断函数的调用 因为中断是有优先级的&#xff0c;假设有多个中断&#xff0c;那么总是优先级高的在进行&#xff0c;如果我们安排多个中断的话&#xff0c;整体设计就会变得很麻烦 我们放在…

K8s系列---【K8s如何配置优雅停机?】

K8s如何配置优雅停机&#xff1f; 应用部署在k8s中&#xff0c;需要设置pod的优雅停机时间(terminationGracePeriodSeconds)&#xff0c;一般大于应用程序中spring.lifecycle.timeout-per-shutdown-phase设置的超时时间&#xff1b;设置之后服务更新或者重启时k8s会捕获到1号进…

2 push方法的使用(相当于python的append方法)

push方法相当于python的append方法&#xff0c;用来添加数组元素。 另外&#xff0c;数组取元素也是使用data[i]的格式。 例子&#xff1a; <script>var dataList [[1,2,3,4,5,6],[7,8,9,1,2,3]];var x dataList[0];console.log(x);dataList.push([1,1,2,3,4,5]);cons…

leetcode 47. 全排列 II

2023.7.23 这道题是上一题全排列 的一个升级版。 唯一区别就是需要增加一个树层去重的操作&#xff0c;因为数组nums中允许有重复的元素了&#xff0c;而上一题没有重复元素。 下面看代码&#xff1a; class Solution { public:vector<vector<int>> ans;vector<…

MySQL存储过程——概念及基本语法

1.什么时存储过程 2.存储过程操作语法 2.1 创建和调用 2.2 查看和删除 show create procedure p1;删除存储过程 drop procedure if exists p1;

Linux6.11 Docker 网络

文章目录 计算机系统5G云计算第四章 LINUX Docker 网络及Cgroup资源限制一、Docker 网络实现原理二、Docker 的网络模式1.网络模式详解1&#xff09;host模式2&#xff09;container模式3&#xff09;none模式4&#xff09;bridge模式5&#xff09;自定义网络 三、资源控制1.CP…

5.2 Bootstrap 过渡效果(Transition)插件

文章目录 Bootstrap 过渡效果&#xff08;Transition&#xff09;插件使用案例 Bootstrap 过渡效果&#xff08;Transition&#xff09;插件 过渡效果&#xff08;Transition&#xff09;插件提供了简单的过渡效果。 注意&#xff1a;如果您想要单独引用该插件的功能&#xff0…

如何在 Linux 中创建和使用别名命令

动动发财的小手&#xff0c;点个赞吧&#xff01; Linux 用户经常需要反复使用一个命令。一遍又一遍地键入或复制相同的命令会降低您的工作效率并分散您对应该做的事情的注意力。 您可以通过为最常用的命令创建别名来节省一些时间。别名就像自定义快捷方式&#xff0c;代表可以…

FM算法介绍

文章目录 1. 逻辑回归模型的不足2. POLY2模型——特征交叉的开始3. FM模型——隐向量特征交叉4. FFM模型——引入特征域的概念5. 从POLY2到FFM的模型演化过程6. 参考书籍 1. 逻辑回归模型的不足 逻辑回归作为一个基础模型&#xff0c;显然有其简单、直观、易用的特点。 但其局…

第二讲:MySQL安装及启动 Windows

目录 1.MySQL安装及启动2.MySQL常用命令&#xff1a; 1.MySQL安装及启动 1、官网下载 官网入口&#xff1a;官网 点击下载。 2、双击打开安装包 3、安装 4.设置密码&#xff08;随便设置能记住就行&#xff09; 5.配置环境变量 6、找到安装的MySQL路径&#xff0c;复制到上方…

经典CNN(二):ResNet50V2算法实战与解析

&#x1f368; 本文为&#x1f517;365天深度学习训练营中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊|接辅导、项目定制 1 论文解读 在《Identity Mappings in Deep Residual Networks》中&#xff0c;作者何凯明先生提出了一种新的残差单元&#xff0c;为区别原始…

MOS,PCB如何添加散热孔、过孔

一、什么是 PCB 散热孔&#xff1f; 散热孔是利用贯通PCB板的通道&#xff08;过孔&#xff09;使热量传导到背面来散热的手法&#xff0c;配置在发热体的正下方或尽可能靠近发热体。 散热孔是利用PCB板来提高表面贴装部件散热效果的一种方法&#xff0c;在结构上是在PCB板上…

element-ui里的el-table在grid布局下切换数据有滚动条时不断增加?

今天在项目里面遇到了这个问题&#xff0c;相当炸裂&#xff0c;看了半天都没有看出什么问题&#xff0c;很是逆天&#xff0c;记录一下 下面使用代码情景复现一下&#xff1a;el-table 是在 grid 布局下面的&#xff0c;不是子层级&#xff0c;中间还有一层 content 的元素包…

【数据结构】差分数组

【数据结构】差分数组 差分数组二维差分数组二维数组的前缀和 差分数组 如果给定一个包含1000万个元素的数组&#xff0c;同时假定会有频繁区间修改操作&#xff0c;但是不会有频繁的查询操作&#xff0c;比如对某个范围【l&#xff0c;r】内的数字加上某个数字&#xff0c;此时…

Java基础-->异常

什么是异常&#xff1f; 异常&#xff1a;异常就是代表程序出现的问题 误区&#xff1a;不是让我们以后不出现异常&#xff0c;而是程序出了异常之后该如何处理 Error 代表系统级别的错误&#xff08;属于原重问题&#xff09; 系统一旦出现问题&#xff0c;sun公司会把这些…

数据库应用:Mycat实现读写分离

目录 一、理论 1.Mycat 2.Mycat安装启动 3.Mycat搭建读写分离 4.垂直分库 5.水平分表 6.Mycat高可用 7.Mycat安全设置 8.Mycat监控工具 二、实验 1.Mycat读写分离 2.Mycat监控安装 三、问题 1.Mycat命令无法补全 2.Mycat启动失败 3.zookeeper启动报错 四、总结…

基于SpringBoot+Vue的冬奥会科普平台设计与实现

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架…

Java通过URL对象实现简单爬虫功能

目录 一、URL类 1. URL类基本概念 2. 构造器 3. 常用方法 二、爬虫实例 1. 爬取网络图片&#xff08;简易&#xff09; 2. 爬取网页源代码 3. 爬取网站所有图片 一、URL类 1. URL类基本概念 URL&#xff1a;Uniform Resource Locator 统一资源定位符 表示统一资源定位…

动态规划--回文串问题

一)回文子串: 647. 回文子串 - 力扣&#xff08;LeetCode&#xff09; 思路1:暴力枚举: for(int i0;i<array.length;i) for(int ji;j<array.length;j) 我们的中心思路就是枚举出所有的子字符串&#xff0c;然后进行判断所有的子串是否是回文串 思路2:中心扩散: 我们从左向…

​MySQL高阶语句(三)

目录 1、内连接 2、左连接 3、右连接&#xff1a; 二、存储过程⭐⭐⭐ 4. 调用存储过程 5.查看存储过程 5.1 查看存储过程 5.2查看指定存储过程信息 三. 存储过程的参数 3.1存储过程的参数 3.2修改存储过程 四.删除存储过程 MySQL 的连接查询&#xff0c;通常都是将来…