Spring 通过注解来读取和存储对象

1.存储Bean对象

之前的是需要再 spring-config.xml 下 导入bean的:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2sxmV5zx-1682314567098)(assets/image-20230421175412677.png)]

1.1 前置工作: 配置扫描路径 (重要)

<?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.beans"></content:component-scan>
</beans>

在这里指定的是com.beans目录

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gbshskqr-1682314567099)(assets/image-20230421180700724.png)]

也就是所有要存放到spring当中的bean,都要在这个目录下, 或者子目录下.

1.2 添加注解存储Bean对象

简单将 bean 存储到容器:

a) 五大注解:

  • @Conroller [控制器]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fsDeLovG-1682314567099)(assets/image-20230421182338203.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NUzV5Uiu-1682314567100)(assets/image-20230421182311133.png)]

  • @Service [服务]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kTg79ucj-1682314567100)(assets/image-20230421192647019.png)]

  • @Repoistory [仓库]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NkYnN5sO-1682314567100)(assets/image-20230421192659055.png)]

  • @Configuration [配置]

    PS: 注意这里添加的注解是Configuration 而不是Configurable 否则会添加失败

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5TfxpchL-1682314567101)(assets/image-20230421192736378.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3Ro7aRgJ-1682314567101)(assets/image-20230421192812199.png)]

  • @Component [组件]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JeJLPOUd-1682314567102)(assets/image-20230421192821201.png)]

控制类端代码:

import com.beans.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
    public static void main(String[] args) {
        //1.先得到上下文对象
        ApplicationContext context
                = new ClassPathXmlApplicationContext("spring-config.xml");
        //2.得到bean
        UserController controller = context.getBean("userController", UserController.class);
        controller.sayHi();
        UserService service = context.getBean("userService", UserService.class);
        service.sayHello();
        UserRepository repository = context.getBean("userRepository",UserRepository.class);
        repository.sayHi();
        UserConfig config = context.getBean("userConfig",UserConfig.class);
        config.sayHi();
        UserComponent component = context.getBean("userComponent",UserComponent.class);
        component.sayHi();
    }
}

运行结果如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WC49a7DS-1682314567102)(assets/image-20230421192834511.png)]

可以发现能够真正常运行, 那么, 如果不加注解会出现什么样的效果呢?

会出现运行异常 NoSuchBeanDefinitionException错误信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CRxgaNDL-1682314567102)(assets/image-20230421190030279.png)]

如果Bean对象并不在扫描的路径 会出现什么样的效果呢?

其实是同样的异常 ,没有找到bean定义的对象 . 因此,指定扫描路径以及添加注解非常重要.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e6mn0VOE-1682314567103)(assets/image-20230421190321928.png)]

此时还有一个问题:

五大注解都是能够添加Bean的, 那么他们的区别是什么?

为什么需要五大类注解?

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

  • Controller 负责和前端数据的校验控制
  • Service 就是负责数据的组装和接口的调用
  • Resository就是和数据库进行交互的层面, 也就是DAO层

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2oxXSTSn-1682314567103)(assets/image-20230421195930579.png)]

五大类注解的关系?

查看 Controller , Service , Respository ,Configuration 的源码:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-098dH0HQ-1682314567103)(assets/image-20230421200400541.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WbGJbdyQ-1682314567104)(assets/image-20230421200421545.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9T5xJdoo-1682314567104)(assets/image-20230421200452769.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZnJZ1Xrb-1682314567105)(assets/image-20230421200512863.png)]

我们发现,@Controller ,@Service @Configuration @Responsitory 都是基于@Component注解实现的,

因此 @Component 是其他4个注解的父类.


查看注解生成Bean name 的代码, 了解生成Bean name的机制

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zXbAzLWv-1682314567105)(assets/image-20230421203655000.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w385ct3t-1682314567105)(assets/image-20230421203953809.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F92Q908L-1682314567106)(assets/image-20230421204005438.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EkXKbgpp-1682314567106)(assets/image-20230421204040227.png)]

b) 通过@Bean 方法

  1. 创建一个User类

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xeVL7UKf-1682314567106)(assets/image-20230421205822492.png)]

  2. 创建UserBeans类,用来存放User对象的方法

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BeZc57j2-1682314567107)(assets/image-20230421205638356.png)]

    PS: ** bean是添加到方法上的,并且@Bean注解是不能单独存在的,需要五大注解**的加持

  3. 调用 当Context对象通过bean name 获取到对象的时候 就已经调用了该方法.

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-66iB0HPS-1682314567107)(assets/image-20230421205622587.png)]

    结果如下:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8rBArZQY-1682314567107)(assets/image-20230421205813810.png)]

    方法注解默认的Bean name 是 方法名, 但是也可以指定name(推荐) , 此时通过方法名获取Bean name这个方法就会失效

    在这里插入图片描述

    首先试着调用user1试试还会不会生效:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EoUOTxL4-1682314567108)(assets/image-20230422090757023.png)]

    结果就是报错了 :

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9jTXTBBB-1682314567109)(assets/image-20230422090805919.png)]

    再使用指定的方法name 来获取Bean name :

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-po2Vvgxh-1682314567109)(assets/image-20230422090923430.png)]

    结果如下:

    成功获取到当前Bean方法的user对象了

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hn6g2cRo-1682314567110)(assets/image-20230422090931764.png)]

2. 获取Bean对象

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

对象装配(对象注入)的实现方法以下三种:(注入的三种方式)

1.1三种注入方式

  1. 属性注入(字段注入)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kf8hEQRP-1682314567110)(assets/image-20230422121428762.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3p6NbJ2r-1682314567110)(assets/image-20230422121440439.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5M25r8os-1682314567111)(assets/image-20230422121451546.png)]

  2. 构造方法注入
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y9yTYnf7-1682314567111)(assets/image-20230422121551026.png)]

  3. Setter注入

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1aMQvy9L-1682314567111)(assets/image-20230422121527477.png)]

属性注入,构造方法注入,setter注入的区别:

  1. 属性注入特点是写法简单, 但是通用性不好, 它只能运行在Ioc容器下,如果是非Ioc容器就会出现问题(空指针异常)
  2. Setter注入: 早期Spring版本推荐Setter注入,Setter注入通用性没有构造方法注入通用.
  3. 构造方法注入的好处:通用性更好,它能确保在注入对象之前, 此注入对象一定能被初始化,但是当注入方法注入参数过多时,此时开发者就需要检查自己写的代码是否符合单一设计原则的规范,此注入方式也是spring后期版本中推荐的注入方式.

1.2 两种注入方法

  1. @Resource
  2. @Aurowired

注入的两种方法的区别:

@Resource vs @Autowired

  1. 出身不同: @Resource 来自于Jdk , @Autowried 时 Spring 框架提供的
  2. 用法不同: @Autowired 支持属性注入,构造方法注入和Setter注入, 而 @Resource 不支持构造方法注入
  3. 支持参数不同: @Resource 支持更多的参数设置,(name,type 设置…),而 @Autowired 只支持 required 参数

2.1当 @Bean 将一个类型对象注入多次的问题

UserBeans类将对象User注入了两次:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FwIEN92f-1682314567112)(assets/image-20230422121701531.png)]

App类中:如

ApplicationContext context
                = new ClassPathXmlApplicationContext("spring-config.xml");

        UserController controller = context.getBean("userController", UserController.class);
        controller.sayHi();

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y1eVvpDl-1682314567112)(assets/image-20230422121921369.png)]

此时就会报错: 也是因为 在UserController内部匹配到了两个User对象, 但是期望的时唯一一个

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BwqtNtCr-1682314567112)(assets/image-20230422122040541.png)]

2.2 解决方案

方案1: 直接指定变量名和bean name 相同

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-shg8TzcY-1682314567113)(assets/image-20230422122232974.png)]

方案2: 使用@Resource设置name / 使用@Autowired 搭配 @Qualifier value属性来指定注入对象:

  • 使用@Resource设置name:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Df8nqiXM-1682314567113)(assets/image-20230422122351915.png)]

* [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ypmpS7Mw-1682314567113)(assets/image-20230422122408894.png)]

运行结果 :

匹配成功

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oF4xWuUp-1682314567114)(assets/image-20230422122435639.png)]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值