【Spring】更简单的读取和存储对象,五大类注解

这篇具有很好参考价值的文章主要介绍了【Spring】更简单的读取和存储对象,五大类注解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

经过前面的学习,我们已经可以实现基本的 Spring 读取和存储对象的操作了,但在操作的过程中我们发现读取和存储对象并没有想象中的那么 “简单”,所以接下来我们要学习更加简单的操作 Bean 对象的方法

在 Spring 中想要更简单的存储和读取对象的核心是使用注解,也就是我们接下来要学习 Spring 中的相关注解,来存储和读取 Bean 对象

一、存储 Bean 对象

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

<bean id="user" class="com.beans.User"></bean>

而现在我们只需要⼀个注解就可以替代之前要写一行配置的尴尬了,不过在开始存储对象之前,我们先要来点准备工作。


1、前置⼯作:配置扫描路径(重要)

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

在 resources 中创建 spring-config.xml 文件

——在 spring-config.xml 中设置 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=""></content:component-scan>
</beans>

在 java 中创建一个 package:com.beans,这就是所有要存放到 spring 中的 bean 的根路径

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

注意: 只会扫描对应的目录,包括在根目录下的子目录的所有类都可以被扫描


2、通过五大类注解存储 Bean 对象

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

  1. 类注解:

    @Controller 控制器

    @Service 服务

    @Repository 仓库

    @Component 配置

    @Configuration 组件

  2. 方法注解:

    @Bean


3、五大类注解

3.1、Controller(控制器存储)

在 com.beans 下创建一个类 UserController

使⽤ @Controller 存储 bean 的代码如下所示: @Controller 不能省略

import org.springframework.stereotype.Controller;

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

此时我们先使⽤之前读取对象的⽅式来读取上⾯的 UserController 对象,如下代码所示:

【Spring】更简单的读取和存储对象,五大类注解,Java,spring,java,后端,注解,java-ee


3.2、@Service(服务存储)

使⽤ @Service 存储 bean 的代码如下所示

@Service
public class UserService {
    public void sayHi() {
        System.out.println("hello, UserService! ");
    }
}

读取 bean 的代码:

public class App {
    public static void main(String[] args) {
        // 1、先得到上下文对象
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        // 2、得到 bean 对象
        UserService service = context.getBean("userService", UserService.class);
        // 3、使用 bean
        service.sayHi();
    }
}

3.3、@Repository(仓库存储)

使⽤ @Repository 存储 bean 的代码如下所示:

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

读取 bean 的代码:

public class App {
    public static void main(String[] args) {
        // 1、先得到上下文对象
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        // 2、得到 bean 对象
        UserRepository repository = context.getBean("userRepository", UserRepository.class);
        // 3、使用 bean
        repository.sayHi();
    }
}

3.4、@Component(组件存储)

使⽤ @Component 存储 bean 的代码如下所示:

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

读取 bean 的代码:

public class App {
    public static void main(String[] args) {
        // 1、先得到上下文对象
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        // 2、得到 bean 对象
        UserComponent component = context.getBean("userComponent", UserComponent.class);
        // 3、使用 bean
        component.sayHi();
    }
}

3.5、@Configuration(配置存储)

使⽤ @Configuration 存储 bean 的代码如下所示:(注意不是 @Configurable)

@Configuration
public class UserConfig {
    public void sayHi() {
        System.out.println("hello, UserConfig");
    }
}

读取 bean 的代码:

public class App {
    public static void main(String[] args) {
        // 1、先得到上下文对象
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        // 2、得到 bean 对象
        UserConfig config = context.getBean("userConfig", UserConfig.class);
        // 3、使用 bean
        config.sayHi();
    }
}

4、为什么要这么多类注解

既然功能是⼀样的,为什么需要这么多的类注解呢?

让代码的可读性提高,让程序员能够直观的判断当前类的用途。

这和为什么每个省/市都有⾃⼰的⻋牌号是⼀样的?⽐如陕⻄的⻋牌号就是:陕X:XXXXXX,北京的⻋牌号:京X:XXXXXX,⼀样。甚⾄⼀个省不同的县区也是不同的,⽐如⻄安就是,陕A:XXXXX,咸阳:陕B:XXXXXX,宝鸡,陕C:XXXXXX,⼀样。这样做的好处除了可以节约号码之外,更重要的作⽤是可以直观的标识⼀辆⻋的归属地。

那么为什么需要怎么多的类注解也是相同的原因,就是让程序员看到类注解之后,就能直接了解当前类
的⽤途,⽐如:

  • @Controller:表示的是业务逻辑层;
  • @Servie:服务层;
  • @Repository:持久层;
  • @Configuration:配置层。

程序的⼯程分层,调⽤流程如下:

【Spring】更简单的读取和存储对象,五大类注解,Java,spring,java,后端,注解,java-ee

4.1、类注解之间的关系

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

【Spring】更简单的读取和存储对象,五大类注解,Java,spring,java,后端,注解,java-ee

其实这些注解⾥⾯都有⼀个注解 @Component,@Controller / @Service / @Repository / @Configuration 是基于 @Component 实现的,@Component 可以认为是其他 4 个注解的父类


5、Spring 使用5大类注解生成 beanName 问题

创建类 APIController,使用 getBean() 获取 bean 对象,如果 beanName 使用首字母小写,出现错误:

【Spring】更简单的读取和存储对象,五大类注解,Java,spring,java,后端,注解,java-ee

如果使用原类名,运行成功:

APIController apiController = context.getBean("APIController", APIController.class);

5.1、查询 Spring 关于 bean 存储时⽣成的命名规则

——在 Idea 中使⽤搜索关键字“beanName”可以看到以下内容:

【Spring】更简单的读取和存储对象,五大类注解,Java,spring,java,后端,注解,java-ee

Spring 原码与注释

【Spring】更简单的读取和存储对象,五大类注解,Java,spring,java,后端,注解,java-ee

——查看原码:

【Spring】更简单的读取和存储对象,五大类注解,Java,spring,java,后端,注解,java-ee

——来到了 .java 文件,说明不是 spring 的方法,打开当前类所在的目录:

【Spring】更简单的读取和存储对象,五大类注解,Java,spring,java,后端,注解,java-ee

说明 spring 生成 beanName 的方法是 JDK 自身的方法

【Spring】更简单的读取和存储对象,五大类注解,Java,spring,java,后端,注解,java-ee

——bean 对象的命名规则的⽅法,使⽤的是 JDK Introspector 中的 decapitalize ⽅法,源码如下:

【Spring】更简单的读取和存储对象,五大类注解,Java,spring,java,后端,注解,java-ee

验证:

import java.beans.Introspector;

public class App2 {
    public static void main(String[] args) {
        String className1 = "UserController";
        String className2 = "APIController";
        System.out.println(Introspector.decapitalize(className1)); // userController
        System.out.println(Introspector.decapitalize(className2)); // APIController
    }
}

6、——⽅法注解

类注解是添加到某个类上的,⽽⽅法注解是放到某个⽅法上的

创建类 User,添加 Getter && Setter 和 toString 方法::

package com.beans;

public class User {
    private int id;
    private String name;
}

创建类 UserBeans,添加一个 user1 方法:

public class UserBeans {
    @Bean
    public User user1() {
        User user = new User();
        user.setId(1);
        user.setName("zhangsan");
        return user;
    }
}

获取 bean 对象: 方法注解的 beanName 是方法名

【Spring】更简单的读取和存储对象,五大类注解,Java,spring,java,后端,注解,java-ee

使用类型获取 bean: 可以通过类型获取 bean 对象,但是添加一个 user2 方法,就会报错

【Spring】更简单的读取和存储对象,五大类注解,Java,spring,java,后端,注解,java-ee


6.1、方法注解要配合类注解使用

说明没有成功将对象注入到 spring 中,在 Spring 框架的设计中,方法注解 @Bean 要配合类注解才能将对象正常的存储到 Spring 容器中

修改代码:

@Component
public class UserBeans {
    @Bean // 注意:只使用一个 @Bean 是无法将对象存储到容器中的
    public User user1() {
        User user = new User();
        user.setId(1);
        user.setName("zhangsan");
        return user;
    }
}

运行结果: User{id=1, name=‘zhangsan’}


7、重命名 Bean

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

@Component
public class UserBeans {
    @Bean(name = "userInfo")
    public User user1() {
        User user = new User();
        user.setId(1);
        user.setName("zhangsan");
        return user;
    }
}

使用:

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

这个重命名的 name 其实是⼀个数组,⼀个 bean 可以有多个名字,@Bean(name = {"userInfo", "userTest"})

并且 name= 可以省略 @Bean({"userInfo", "userTest"})


7.1、Bean 命名规则

注意: 重命名之后,使用原来的方法名是否能正确获取到对象?

User user = context.getBean("user1", User.class);

报错:No bean named ‘user1’ available

  • 当没有设置 name 属性时,那么 bean 默认的名称就是方法名,
  • 当设置了 name 属性之后,只能通过重命名的 name 属性对应的值来获取,也就是说,重命名之后,再使用方法名就获取不到 bean 对象

二、获取 Bean 对象(对象装配)

1、对象装配(对象注入)的实现

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

实现方法有以下三种:

  • 属性注入

  • 构造方法注入

  • Setter 注入


1.1、属性注入 @Autowired

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

——UserController:

/**
 * 根据属性实现 bean 对象的注入
 */
@Controller
public class UserController {
    @Autowired
    private UserService userService;
    
    public void sayHi() {
        userService.sayHi();
    }
}

告诉 spring 在加载 UserController 时,先将 UserService 对象,注入当前类的 userService 属性中。前提是 UserService 已经被注入到 spring 中,

——UserService:

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

——验证:

运行结果:hello, UserService

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

1.2、构造方法注入

(官方推荐的写法)

如果当前类中只存在一个构造方法,那么@Autowired 注解可以省略

——UserController2:

/**
 * 使用构造方法实现 bean 注入
 */
@Controller
public class UserController2 {
     private UserService userService;
     
     @Autowired
     public UserController2(UserService userService) {
         this.userService = userService;
     }

     public void sayHi() {
         userService.sayHi();
     }

     // 传统写法
     // public UserController2() {
     //    userService = new UserService();
     //
     //}
}

——验证:

运行结果:hello, UserService

public class App {
    public static void main(String[] args) {
        // 1、得到上下文对象
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        UserController2 userController2 = context.getBean(UserController2.class);
        userController2.sayHi();
    }
}

1.3、Setter 注入

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

——UserController3:

@Controller
public class UserController3 {
    private UserService userService;

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

    public void sayHi() {
        userService.sayHi();
    }
}

——验证:

运行结果:hello, UserService

public class App {
    public static void main(String[] args) {
        // 1、得到上下文对象
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        UserController3 userController3 = context.getBean(UserController3.class);
        userController3.sayHi();
    }
}

1.4、三种注⼊方式优缺点分析

属性注⼊: 优点是简洁,使⽤⽅便;缺点是只能⽤于 IoC 容器,如果是⾮ IoC 容器不可⽤,并且只有在使⽤的时候才会出现 NPE(空指针异常)

构造⽅法注⼊:Spring 推荐的注⼊⽅式,它的缺点是如果有多个注⼊会显得⽐较臃肿,但出现这种情况你应该考虑⼀下当前类是否符合程序的单⼀职责的设计模式了,它的优点是通⽤性在使⽤之前⼀定能把保证注⼊的类不为空

Setter ⽅式:Spring 前期版本推荐的注⼊⽅式,但通⽤性不如构造⽅法,所有 Spring 现版本已经推荐使⽤构造⽅法注⼊的⽅式来进⾏类注⼊了


1.5、@Resource:另⼀种注⼊关键字

将以上三种对象注入的实现改成 @Resource:属性注入,Setter 注入可以正常运行,而构造方法注入出现问题:

【Spring】更简单的读取和存储对象,五大类注解,Java,spring,java,后端,注解,java-ee

两种注入方法@Autowired 和 @Resource 的区别:

  • 出身不同: @Autowired 来⾃于 Spring,⽽ @Resource 来⾃于 JDK 的注解;

  • 使⽤时支持设置的参数不同: @Autowired 只支持 required 参数设置,相⽐于 @Autowired 来说,@Resource ⽀持更多的参数设置,例如 name, type 设置,根据名称获取 Bean

  • 用法不同: @Resource支持属性注入和 Setter 注入,但不支持构造方法注入


2、Bean 将一个类型的对象注入多次的问题

注入一个 User 对象,运行观察是否可以正常打印

UserController

@Controller
public class UserController {
    @Resource
    public User user;

    public void sayHi() {
        System.out.println("User —— " + user);
    }
}

UserBeans

@Component
public class UserBeans {
    @Bean(name = "userInfo")
    public User user1() {
        User user = new User();
        user.setId(1);
        user.setName("zhangsan");
        return user;
    }
    
    @Bean
    public User user2() {
        User user = new User();
        user.setId(1);
        user.setName("lisi");
        return user;
    }
}

App

public class App {
    public static void main(String[] args) {
        // 1、得到上下文对象
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        // 2、通过上下文对象的 getBean 方法获取 bean 对象
        UserController controller = context.getBean(UserController.class);
        // 3、使用 bean
        controller.sayHi();
    }
}

报错信息: No qualifying bean of type ‘com.beans.User’ available: expected single matching bean but found 2: userInfo,user2


2.1、解决方案

1、精确地描述 bean 的名称(将注入的名称写对)。

修改代码:

@Controller
public class UserController {
    @Resource
    public User user2;

    public void sayHi() {
        System.out.println("User —— " + user2);
    }
}

运行结果: User —— User{id=1, name=‘lisi’}

2、使用 @Resource 设置 name 的方式来重命名注入对象

修改代码:

@Controller
public class UserController {
    @Resource(name = "user2")
    public User user;

    public void sayHi() {
        System.out.println("User —— " + user);
    }
}

3、使用 Autowired +Qualifier 来筛选 bean 对象

value 可以省略:@Qualifier(“user2”),不建议省略

@Controller
public class UserController {
    @Autowired
    @Qualifier(value = "user2")
    public User user;

    public void sayHi() {
        System.out.println("User —— " + user);
    }
}

综合练习

在 Spring 项⽬中,通过 main ⽅法获取到 Controller 类,调⽤ Controller ⾥⾯通过注⼊的⽅式调⽤Service 类,Service 再通过注⼊的⽅式获取到 Repository 类,Repository 类⾥⾯有⼀个⽅法构建⼀个User 对象,返回给 main ⽅法。Repository ⽆需连接数据库,使⽤伪代码即可文章来源地址https://www.toymoban.com/news/detail-613733.html


到了这里,关于【Spring】更简单的读取和存储对象,五大类注解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring使用注解存储和读取对象

    之前我们存储Bean时,需要在spring-config.xml中添加bean注册才行,这样的方式并不简单。我们要想 更简单的存储和读取对象的核心是使用注解 1.使用类注解(五大类注解): @Controller:控制器,验证用户请求的数据正确性(安保系统) @Service:服务层,编排和调度具体执行方法的(客服

    2023年04月19日
    浏览(34)
  • 【Spring】(三)Spring 使用注解存储和读取 Bean对象

    前面的文章详细的介绍了 Spring 对象的创建,以及对 Bean 对象的存取操作,但是通过配置文件注册 Bean 对象以及使用 ApplicationContext 或 BeanFactory 的方式获取 Bean 对象的操作就显得格外的复杂。因此,本文主要就是详细介绍了一种更加简单的方式来实现对 Bean 对象更加简单的储

    2024年02月14日
    浏览(28)
  • 【Spring】使用注解读取和存储Bean对象

     哈喽,哈喽,大家好~ 我是你们的老朋友: 保护小周ღ    谈起Java 圈子里的框架,最年长最耀眼的莫过于 Spring 框架啦,本期给大家带来的是:  将对象存储到 Spring 中、Bean 对象的命名规则、从Spring 中获取bean 对象、注入的、@Autowired 与 @Resource 的区别、解决@Bean 方

    2024年02月13日
    浏览(37)
  • Spring 更简单的读取和存储对象

    在 Spring 中要想更简单的存储和读取对象 , 核心是 使用注解 , 所以我们需要通过 Spring 中相关注解 , 来存储和读取 Bean 对象. 之前我们存储 Bean 时 , 需要在 spring-config.xml 中添加一行注释才行: 而现在我们只需一个注解就可以替代之前要写一行配置 , 不过在存储对象之前 , 我们先

    2024年02月02日
    浏览(31)
  • 5-Spring更简单的读取和存储对象

    目录 1.存储Bean对象 1.1.前置工作:在配置文件中设置bean扫描的根路径(重要) 1.2.添加注解存储Bean对象到Spring中 1.2.1.类注解(添加到某个类上,将当前的类存储到Spring中):@Controller,@Service,@Repository,@Component,@Configuration 关于类注解的bean的命名规则: PS:为什么要这么多类

    2023年04月25日
    浏览(35)
  • 【Spring框架全系列】Spring更简单的读取和存储对象

    📬📬哈喽,大家好,我是小浪。上篇博客我们介绍了如何创建一个spring项目,并且如何的存、取对象,介绍了相关方法,那么本篇博客将接着上篇博客的内容介绍如何更加简单的读取和存储对象。 🌃在 Spring 中想要更简单的存储和读取对象的核⼼是使⽤注解,也就是我们接

    2024年02月05日
    浏览(31)
  • Spring更简单的存储和读取Bean对象

    目录 1.第一个Spring项目 2.存储Bean对象 2.1 准备工作 2.2 五大类注解 2.3 方法注解@Bean 2.4 Bean对象的默认命名规则 3. 读取Bean对象 3.1 属性注入 3.2 setter注入 3.3 构造方法注入 3.4 注入异常问题 3.5 注入方式优缺点 3.6 @Autowired和@Resource的区别 在学习更简单的方式来读取和存储Bean对象

    2024年02月03日
    浏览(38)
  • Spring系列3 -- 更简单的读取和存储对象

             上一篇章总结了,Spring的创建与使用,通过创建Maven项目配置Spring的环境依赖,创建Spring框架的项目,然后通过在Resource目录下创建Spring-config.xml配置文件,添加bean/bean标签将我们需要的bean对象注入到容器中,然后通过ApplicationContext获取Spring上下文,使用getBean()方法获取be

    2024年02月13日
    浏览(28)
  • 【JavaEE进阶】Spring 更简单的读取和存储对象

    配置扫描路径是使用注解之前的前置工作,是非常重要的,是必须的操作项.只有被配置的包下的所有类,添加了注解才能被正确的识别并保存到 Spring 中. 首先创建一个Spring项目.创建好后,第一步就是配置扫描路径:在 resources 目录中创建一个 spring-config.xml 文件.然后在 spring-config.

    2024年02月12日
    浏览(31)
  • JavaEE 突击 5 - Spring 更简单的读取和存储对象(2)

    大家新年快乐 , 祝大家新的一年如图 这个专栏给大家介绍一下 Java 家族的核心产品 - SSM 框架 JavaEE 进阶专栏 Java 语言能走到现在 , 仍然屹立不衰的原因 , 有一部分就是因为 SSM 框架的存在 接下来 , 博主会带大家了解一下 Spring、Spring Boot、Spring MVC、MyBatis 相关知识点 并且带领

    2024年02月19日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包