设为首页 加入收藏

TOP

0源码基础学习Spring源码系列(一)——Bean注入流程(一)
2023-07-26 08:16:27 】 浏览:161
Tags:Spring Bean

作者:京东科技 韩国凯

通过本文,读者可以0源码基础的初步学习spring源码,并能够举一反三从此进入源码世界的大米!
由于是第一次阅读源码,文章之中难免存在一些问题,还望包涵指正!

一、 @Autowired与@Resource的区别

用一句话总结两者的区别就是: @Autowired会先通过类型注入,即byType,当存在有多个类型时会通过名称注入。@Resource则相反,会先通过名称注入,即byName,当名称不存在或有多个名称时会通过类型注入。

那么通过名称注入与通过类型注入有什么区别呢?

//创建接口
interface StuService{
    String getName();
}

@Service
//Stu2实现接口并注册bean
class Stu2 implements StuService{
    @Override
    public String getName() {
        return "stu2";
    }
}

@Service
//Stu3实现接口并注册bean
class Stu3 implements StuService{
    @Override
    public String getName() {
        return "stu3";
    }
}

1.1 @Autowired

那么此时如果我们对 StuService注入, @Autowired可以选择注入的类型就有两个,分别是 Stu2与 Stu3

需要注意的是,类型有很多种选择:

  1. 当注册bean与获取bean为同一个类时,类型只有这个类本身。

例如,我们有获取session的工具类,需要将其注入到spring之中,

@Component
class SessionUtil{
    public String getSession(){
        return "session";
    }
}

只有一个类,直接注册bean,使用时可以任意选择

@Autowired
SessionUtil sessionUtil;

此时@Autowired只有一个注册类型,直接注入。

  1. 当注册bean有多个时,类型为所有注册的bean,实现方式有:实现接口、继承、通过其他方式,例如xml配置注册bean。

例如上述 StuService有多个实现类,每个实现类都注册了bean,因此@Autowired可以选择的类型就有两个。

@Autowired
StuService stu;

根据上述的@Autowired逻辑,此时有多个类型,那么会根据bean name查找,(即类名首字母小写的),发现 stu没有对应的实现类,

此时会报错:

Field stu in com.example.demo.spring.Stu1 required a single bean, but 2 were found:

只需要将 stu 替换成 stu2或 stu3即可完成注入。

继承和其他方式同时有多个bean注入时同理。

因此,@Autowired中类型的定义可以归结为:当注册bean有多个时,类型为所有注册的bean,实现方式有:实现接口、继承、通过其他方式,例如xml配置注册bean或者@Bean注册。

1.2 @Resource

  1. 当只有一个bean时,可以直接注册
@Autowired
SessionUtil sessionUtil;
  1. 当有多个bean注册时,如果未指定名称,则bean name为类名首字母小写,指定了bean名称则注册名称为该名称。

例如上文中 Stu1 Stu2都未指定bean名称,因此两者的bean名称分别为 stu1 stu2

当使用@Bean在方法上注册bean,此时名称为方法名称。

@Bean()
public Student getStudent(){
    Student student = new Student();
    student.setName("bob");
    student.setId(26);
    return student;
}

此时该bean名称为 getStudent

同样,我们也可以注册bean时自定义bean名称

@Bean("stu1")
public Student getStudent(){
    Student student = new Student();
    student.setName("bob");
    student.setId(26);
    return student;
}

@Service("stu2")
class Stu2 implements StuService{
    @Override
    public String getName() {
        return "stu2";
    }
}

@Component("stu3")
class Stu3 implements StuService{
    @Override
    public String getName() {
        return "stu3";
    }
}

在引用时指定bean:

@Resource(name = "stu2")
private StuService stu1;

1.3 @Autowired

当我们使用@Resource时,会根据名称也就是 stu2去查询,此时bean名称只有一个,查到返回

@Resource
private Stu3 stu2;

但是在执行时却发现报错:

Bean named 'stu2' is expected to be of type 'com.example.demo.spring.Stu3' but was actually of type 'com.example.demo.spring.Stu2'

这是因为只根据了bean名称去查询,却没有根据bean类型,查到的是Stu2类型的bean,但是期望的却是Stu3,因此会发生类型不匹配。

二、SpringIOC的Bean注入流程

spring的注册流程主要包含两个部分:

  1. 容器的启动阶段及预热工作
  2. Bean的注入流程

先了解一下几个概念:

2.1 概念介绍

2.1.1 配置元数据

存在于磁盘上的项目中用于描述一个bean的数据,可以是xml、properties、yaml等静态文件,也可以是各种注解描述的对应信息,例如@Service、@Component描述的一个bean的信息。

<bean id="role" class="com.wbg.springxmlbean.entity.Role">
    <property name="id" value="1"/>
    <property name="roleName" value="高级工程师"/>
    <property name="note" value="重要人员"
首页 上一页 1 2 3 4 5 6 7 下一页 尾页 1/10/10
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Java线程中断 下一篇java基础(五):数组

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目