• Spring 更简单的读取和存储对象


    通过之前的学习,我们也能够实现基本的 Spring 读取和存储对象操作,感觉有点麻烦,接下来, 更简单的存储和读取对象的核心就是使用注解

    1 存储 Bean 对象

    1.1 配置扫描路径(重要)

    先把依赖文件导入pom.xml:

    <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>5.2.3.RELEASE</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-beans</artifactId>
                <version>5.2.3.RELEASE</version>
            </dependency>
        </dependencies>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    接下来写入配置文件,名字最好起的有意义
    在这里插入图片描述

    把这串类容粘贴进去:

    
    <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="beans">content:component-scan>
    
    beans>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述

    1.2 添加注解存储 Bean 对象

    有两种注解类型可以实现:

    1: 使用 5 大类注解实现:@Controller[控制器],@Service[服务],@Repository[仓库],
    @Configuration[配置],Component[组件]

    2: 通过方法注解: @Bean方法

    1.2.1 类注解

    ① @Controller(控制器存储)

    import org.springframework.stereotype.Controller;
    
    @Controller
    public class UserController {
        public void sayHi(String name){
            System.out.println("hello: "+name);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述
    在这里插入图片描述

    后面解释原因.

    ② @Service(服务存储)

    import org.springframework.stereotype.Service;
    
    @Service
    public class UserService {
        public void sayHi(String name){
            System.out.println("hello: "+name);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    ③ @Repository(仓库存储)

    import org.springframework.stereotype.Repository;
    
    @Repository
    public class UserRepository {
        public void sayHi(String name){
            System.out.println("hello: "+name);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    ④ Configuration(配置存储)

    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class UserConfiguration {
        public void sayHi(String name){
            System.out.println("hello: "+name);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    ⑤ Component(组件存储)

    import org.springframework.stereotype.Component;
    
    @Component
    public class UserComponent {
        public void sayHi(String name){
            System.out.println("hello: "+name);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    测试读取 bean 的代码

    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");
            //Controller
            UserController userController = context.getBean("userController",UserController.class);
            userController.sayHi("Controller");
    
            //Service
            UserService userService = context.getBean("userService",UserService.class);
            userService.sayHi("Service");
    
            //Repository
            UserRepository userRepository = context.getBean("userRepository",UserRepository.class);
            userRepository.sayHi("Repository");
    
            //Configuration
            UserConfiguration userConfiguration = context.getBean("userConfiguration",UserConfiguration.class);
            userConfiguration.sayHi("Configuration");
    
            //Component
            UserComponent userComponent = context.getBean("userComponent",UserComponent.class);
            userComponent.sayHi("Component");
            
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    在这里插入图片描述在这里插入图片描述

    注意事项

    1: 读取存入对象的 id 默认情况首字母是要小写的,大写读不到
    在这里插入图片描述在这里插入图片描述

    2: 当第一个字母和第二个字母都大写了,首字母小写就不能读到
    在这里插入图片描述在这里插入图片描述这里就需要去观察源码是怎么实现的了,
    双击shift搜索beanName
    在这里插入图片描述在这里插入图片描述
    它使⽤的是 JDK Introspector 中的 decapitalize ⽅法,源码如下在这里插入图片描述
    像这种情况大写就行了
    在这里插入图片描述

    3: 包路径要写对
    在这里插入图片描述

    为什么需要这么多类注解?

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

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

    程序的⼯程分层,调⽤流程如下:
    在这里插入图片描述

    类注解之间的关系

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

    在这里插入图片描述
    这几个注解都有一个注解@Component,说明了它们本身就是属于@Component"子类"

    1.2.2 @Bean(方法注解)

    类注解是添加到某个类上的,⽽⽅法注解是放到某个⽅法上的,如以下代码的实现:
    先创建一个User类:

    public class User {
        private int id;
        private String name;
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    '}';
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    在创一个UserBean:

    import org.springframework.context.annotation.Bean;
    import org.springframework.stereotype.Component;
    
    @Component
    public class UserBean {
    
        @Bean
        public User user(){
            User user = new User();
            user.setId(1);
            user.setName("张三");
            return user;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    测试读取的内容:

    import beans.User;
    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);
            System.out.println(user.toString());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述

    注意要有类注解,不然获取不到:
    在这里插入图片描述

    如果不加类注解:
    在这里插入图片描述

    方法重命名

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

    在这里插入图片描述

    @Bean 命名规则,当没有设置 name 属性时,那么 bean 默认的名称就是方法名,当设置了name 属性之后,只能通过重命名的 name 属性对应的值来获取,也就是说重命名之后,在使用方法名就获取不到 bean 对象
    在这里插入图片描述

    他也可以重命名多个:
    在这里插入图片描述

    2. 获取 Bean 对象(对象装配)

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

    对象注入(对象装配)[从容器中将对象读取出来]三种方式:

    • 属性注入(字段注入)
    • 构造方法注入
    • Setter注入

    2.1 属性注入

    属性注入使用 @Autowired 实现的,我们来将 Service 类注入到 Controller 类中:
    Service:

    import org.springframework.stereotype.Service;
    
    @Service
    public class UserService {
        public void sayHi(){
            System.out.println("hello,Service!");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    Controller:

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    
    @Controller
    public class UserController {
    
        @Autowired
        private UserService userService;
    
        public void sayHi(){
            userService.sayHi();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    App启动:

    import beans.UserController;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class App2 {
        public static void main(String[] args) {
            ApplicationContext context =
                    new ClassPathXmlApplicationContext("spring-config.xml");
            UserController userController = context.getBean(UserController.class);
            userController.sayHi();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述

    2.2 构造方法注入

    构造⽅法注⼊是在类的构造⽅法中实现注⼊
    在这里插入图片描述

    2.3 Setter注入

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

    在这里插入图片描述

    注:如果当前类里构造方法只有一个, 那么@Autowired是可以被省略的

    三种注入优缺点分析

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

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

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

    2.4 @Resource: 另一种注入关键字

    在进⾏类注⼊时,除了可以使⽤ @Autowired 关键字之外,我们还可以使⽤ @Resource 进⾏注⼊,注意一点的是,@Resource 无法进行构造方法注入

    属性注入:
    在这里插入图片描述

    Setter注入:
    在这里插入图片描述

    构造方法注入就不行:
    在这里插入图片描述

    @Autowired 和 @Resource 的区别

    1: 出身不同: @Resource 来自于 JDK(Java 亲儿子),@Autowired 是 Spring 框架提供的

    2: 用法不同: @Autowired 支持属性注入,构造方法注入,Setter注入,而 @Resource 不支持构造方法注入

    3: 支持的参数不同: @Resource 支持更多的参数设置,比如 name,type 设置,而@Autowired 只支持required 参数设置

    同一个类型多个 @Bean 报错

    在这里插入图片描述

    报错的原因就是非唯一的 Bean 对象

    解决办法:

    1: 精确的描述 bean 的名称(将注入的名称写对)
    在这里插入图片描述

    2: 使用@Resource 设置 name 的方式 来重命名注入对象(如果已经写太多不想改了就可以用这种方式)
    在这里插入图片描述注: @Atowired不能这样设置
    在这里插入图片描述

    3: 使用 @Qualifier来筛选bean对象(@Atowired@Resource都可以)
    在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    [机器学习] 监督学习和无监督学习
    华为云云耀云服务器L实例评测 | 华为云云耀云服务器L实例使用教学
    LeetCode(力扣)17. 电话号码的字母组合Python
    LeetCode 630. 课程表 III - 优先队列&贪心
    利用STM32 HAL库实现USART串口通信,并通过printf重定向输出“Hello World“
    第二十四章 源代码文件 REST API 参考(六)
    数据仓库实验二:关联规则挖掘实验
    3D模型格式全解|含RVT、3DS、DWG、FBX、IFC、OSGB、OBJ等70余种
    Linux下uboot添加自定义命令(详细)实例及原理解析
    2022 极术通讯-搭载“星辰”处理器的聆思科技CSK6视觉AI开发套件开发概览
  • 原文地址:https://blog.csdn.net/chenbaifan/article/details/125654736