Spring如何读取存储Bean对象

这篇文章主要介绍“Spring如何读取存储Bean对象”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Spring如何读取存储Bean对象”文章能帮助大家解决问题。

    配置spring-config文件

    我们之前注册bean是通过在xml配置文件中,通过键值对的方式注册bean对象!
    显然这种方式很麻烦,注册一个对象,就要添加一项!
    有没有什么好的方式可以让spring直接去注册对象!
    yes!

    我们可以直接在配置文件配置好 spring下你要注册对象的包时那个!
    spring启动后,spring就会将bean对象自动注册!

    spring-config配置文件

    <?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">
           <!--在com包下扫描bean注册-->
            <content:component-scan base-package="com"></content:component-scan>
    </beans>

    当然只有一个配置文件显然不够嘛!
    我们如何知道我们代码中的对象是bean对象捏?
    这就要引入spring五大注解概念了!
    我们通过在我们创建好的对象上面添加注解的方式,就是告诉spring这个对象需要注册到容器中!

    类注解和方法注解

    类注解:

    @Controller@Service@Repository@Component@Configuration

    方法注解:
    @Bean

    我们可以通过上述两种注解将对象存储到Spring中!

    @Controller(控制器存储)

    使用@Controller注解存储bean

    package com;
    import org.springframework.stereotype.Controller;
    @Controller //通过Controller注解存储bean对象
    public class UserController {
        public void sayHi(){
            System.out.println("hello Controller注解!");;
        }
    }

    我们通过在UserController类上加上spring类注解,即可完成注册对象!

    在启动类中读取bean对象即可!

    //启动类
    public class app{
        public static void main(String[] args) {
            //1.获取上下文对象
            ApplicationContext context =
                    new ClassPathXmlApplicationContext("spring-config.xml");
            //读取bean对象!
            UserController userController =
                    (UserController) context.getBean("userController");
            //使用
            userController.sayHi();
        }
    }

    如果我们的需要注册的bean对象不在扫描包下,是否又能注册成功呢?

    我们在新建一个controller包在其下创建TestController类,并且通过@Controller注册到Spring中!

    package controller;
    import org.springframework.stereotype.Controller;
    @Controller //注册到Spring中!
    public class TestController {
        public void sayHi(){
            System.out.println("该bean不在扫描的包下");
        }
    }

    然后我们通过ApplicationContext上下文对象读取bean

    可以看到出现异常未找到名为textControllerbean对象!

    结论:只有在扫描包下的类才能被Spring注册

    @Service(服务存储)

    注册bean

    package com;
    
    import org.springframework.stereotype.Service;
    
    @Service // @Service 注解注册对象!
    public class UserService {
        public  void sayHi(){
            System.out.println("Hello Service注解!");
        }
    }

    读取bean

    @Configuration(配置存储)

    package com;
    import org.springframework.context.annotation.Configuration;
    @Configuration //Configuration注解注册bean对象
    public class UserConfiguration {
        public void sayHi(){
            System.out.println("Hello Configuration注解!");
        }
    }

    @Repository(仓库存储)

    package com;
    
    import org.springframework.stereotype.Repository;
    
    @Repository //@Respository 注解注册对象
    public class UserRepository {
        public void sayHi(){
            System.out.println("Hello Respository注解!");
        }
    }

    @Component(组件存储)

    package com;
    
    import org.springframework.stereotype.Component;
    
    @Component //Component注解注册对象!
    public class UserComponent {
        public void sayHi(){
            System.out.println("Hello Component注解!");
        }
    }

    5大类注解联系

    可以看到这5大类注解使用方式一样,都可以对对象进行注册!
    而且注册的方式都一样,既然如此为何还需要5个注解呢?

    我们联系实际生活中的车牌号,我们虽然车牌号的功能都是一样,但是不同地区都有自己的车牌号!我们通过车牌号就可以分辨出这车来自哪里!
    而这里5大类注解作用也是如此,我们通过类注解,可以知道当前类的用途!
    例如;

    @Controller:表示业务逻辑层
    @Service:服务层
    @Repository:持久层
    @Configuration:配置层

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

    我们拿去银行办业务做类比:

    @Controller层就是保安,先要进行检查验证,然后到达Service服务厅询问业务,不同的业务来到Repository,不同的窗口,然后进行相应的工作人员办理业务!

    类注解之前联系:

    可以看到其他4个注解都是Component注解的子类!

    Spring给Bean命名规则

    我们可以看到我们刚刚读取bean对象时,我们并不知道bean对象注册的id而是直接通过userController读取!
    难道说Spring注册bean对象id为类名首字母小写,直接就小驼峰?

    我们查看Spring源码验证!

    我们顺藤摸瓜下方就是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对象的id命名规则如下:

    对象类类名一般采用大驼峰的形式也就是单词第一个字母大小,所以Spring直接bean对象改为小驼峰,`第一个字母分成小写!对象类类名不规范,不是大驼峰,第二个字母和第一个字母都是大小!Spring直接将bean对象命名为类名!

    我们进行验证:

    方法注解@Bean

    我们了解了5大类注解可以进行对象注册,我们使用方法注解进行对象注册!
    注意: 方法注解要和类注解配合使用!

    方法注解进行对象注册

    //User类
    public class User {
        private String name;
        private int id;
        public User(String name, int id) {
            this.name = name;
            this.id = id;
        }
        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    ", id=" + id +
                    '}';
        }
    }
    //Users类
    @Component
    public class Users {
        @Bean
        public User user(){
            return new User("java",666);
        }
    }

    可以看到@Bean注解适用于返回值返回对象的方法中!

    重命名Bean

    我们既然可以通过五大类注解进行对象注入!那为何还要多此一举在方法上加上@Bean方法注解呢?

    我们可以通过@Bean方法注解给bean对象重命名,可以直接设置名字!

    通过 name={"rename1", "rename2"...}可以重命名多个!

    @Component
    public class Users {
        @Bean(name = {"user1"})
        public User user(){
            return new User("java",666);
        }
    }

    能否通过之前Spring给我们设置的名字访问? 不能

    @Bean(name={"user1","user2"}) 重命名多个!

    我们也可以将name省略
    @Bean({"user1"})

    获取Bean对象(对象装配)

    这里可能听了有点迷,啥玩意对象装配,其实就是获取对象!
    我们将对象注册到Spring容器下,我们要读取将对象取出放入到某个类中,这就是对象装配,也叫对象注入!

    实现对象装配的3种方法

    • 属性注入

    • 构造方法注入

    • Setter注入

    下面我们来演示一下这3种注入方式

    我们按照实际开发将Service层的类注入到Controller层的类中!

    属性注入

    我们通过@Autowired实现属性注入
    service层类代码

    @Service
    public class UserService {
        public User getUser(){
            return new User("Mysql",666);
        }
    }

    controller层类代码
    通过属性注入将service层代码注入到这

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

    运行结果:

    构造方法注入

    我们还是通过@Autowired注解注入

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

    Setter注入

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

    三种注入方式对比

    • 属性注入简洁,使用方便! 缺点只能适用于IoC容器,在非IoC容器不适用,并且属性注入只有在是使用的时候才会出现空指针异常(NPE)

    • 构造方法注入现在官方推荐注入方式! 缺点 如果注入多个对象,就会使得代码臃肿,不过这就是程序员的问题了,不符合程序设计的单一职责的设计模式,优点通用性强,在使用前一定可以保证注入的类不为空!

    • Setter方式是Spring前期推荐的注入方式,通用性不如构造方法注入,现在已经认准构造方法注入!

    在进行类注入时,我们还可以通过@Resource注解进行注入!
    我们只需要将@Autowired注解换成@Resource即可!

    @Autowired@Resource区别

    • 出身不同: @Autowired注解是Spring提供的,@Resource是来自JDK下的注解

    • 使用设置的参数不同:相比@Autowired注解,@Resource注解 支持更多的参数设置 例如name设置,根据name获取对象

    注入同一类型多个Bean对象

    我们在Users类中注册了2个相同类型的Bean对象!

    @Component
    public class Users {
        @Bean(name = "user1")
        public User user1(){
            User user =  new User("java",666);
            return user;
        }
        @Bean(name = "user2")
        public User user2(){
            User user = new User("MySQL",666);
            return user;
        }
    }

    当我们直接注入到Controller类中!

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

    因为我们在Spring中注册了2个相同类型的User对象,所以进行对象装配时,也需要通过name属性进行声明你要装配的对象名!

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

    注意:

    @Resource注解才提供了name属性,如果用@Autowried需要加上@Qualifier 注解定义名称

    @Controller
    public class UserController {
    //    @Resource(name = "user2")
        @Autowired
        @Qualifier(value = "user1")
        private User user;
        public User getUser(){
            return user;
        }
    }

    关于“Spring如何读取存储Bean对象”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注本站行业资讯频道,小编每天都会为大家更新不同的知识点。

    相关推荐:

    Spring常见的十大错误,78%的老程序员都踩过这些坑!

    首先我们来看一下,Spring常见错误有那些 太过关注底 内部结构“泄露” 缺乏关注点分离 缺乏异常处理或处理不当 多线程处理不当 不使用基于注解的验证 (依旧)使用基于xml的配置 忽略profile 无法接受依赖项注入 缺乏测试,或测试不当 接下来就一一介绍这些常见的错误1.错误一:太过关注底层...

    好程序员Java学习路线分享Spring创建Bean的3种方式

    好程序员Java学习路线分享Spring创建Bean的3种方式,本文讲解了在Spring应用中创建Bean的多种方式,包括自动创建,以及手动创建注入方式,实际开发中可以根据业务场景选择合适的方案。方式1:使用SpringXML方式配置,该方式用于在纯Spring应用中,适用于简单的小应用,当应用变得...

    追踪JVM中的本地内存

    1.概述 有没有想过为什么Java应用程序通过众所周知的-Xms和-Xmx调优标志消耗的内存比指定数量多得多?出于各种原因和可能的优化,JVM可以分配额外的本机内存。这些额外的分配最终会使消耗的内存超出-Xmx限制。 在本教程中,我们将列举JVM中的一些常见内存分配源,以及它们的大小调整标志,然后学...

    在用Spring boot搭建项目的时候出现 “无法访问此网站“ 是什么情况

    这篇文章主要讲解了“在用Springboot搭建项目的时候出现“无法访问此网站“是什么情况”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“在用Springboot搭建项目的时候出现“无法访问此网站“是什么情况”吧!在用Springboot搭建项目的时候...

    SpringBoot启动机制(starter机制)核心原理详解

    作者:MyBug 一、前言 使用过springboot的同学应该已经知道,springboot通过默认配置了很多框架的使用方式帮我们大大简化了项目初始搭建以及开发过程。本文的目的就是一步步分析springboot的启动过程,这次主要是分析springboot特性自动装配。那么首先带领大家回顾一下以往...

    一道78%的Java程序员搞不清的Spring bean面试题

    熟悉Spring开发的朋友都知道Spring提供了5种scope分别是singleton、prototype、request、session、globalsession。如下图是官方文档上的截图,感兴趣的朋友可以进去看看这五种分别有什么不同。今天要介绍的是这五种中的前两种,也是Spring最初提供的...

    SpringBoot2.0 基础案例(03):配置系统全局异常映射处理

    一、异常分类 这里的异常分类从系统处理异常的角度看,主要分类两类:业务异常和系统异常。 1、业务异常 业务异常主要是一些可预见性异常,处理业务异常,用来提示用户的操作,提高系统的可操作性。常见的业务异常提示:1)请输入xxx2)xxx不能为空3)xxx重复,请更换 2、系统异常 系统异常主要是一些不...