Spring中byName和byType的区别及说明

 更新时间:2022年12月28日 09:53:39   作者:king_weng  
这篇文章主要介绍了Spring中byName和byType的区别及说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

测试实例

Cat类:

public class Cat {
    public void sound(){
        System.out.println("miao~");
    }
}

Dog类:

public class Dog {
    public void sound(){
        System.out.println("wang~");
    }
}

People类:

public class People {
    private Cat cat;
    private Dog dog;
    private String name;
 
    public Cat getCat(){
        return cat;
    }
 
    public void setCat(Cat cat) {
        this.cat = cat;
    }
 
    public Dog getDog(){
        return dog;
    }
 
    public void setDog(Dog dog) {
        this.dog = dog;
    }
 
  public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
}

xml配置文件:

<?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:context="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
       http://www.springframework.org/schema/context/spring-context.xsd">
 
    <bean id = "cat" class="com.hello.pojo.Cat"/>
    <bean id = "dog" class="com.hello.pojo.Dog"/>
 
    <bean id = "people" class="com.hello.pojo.People">
        <property name="cat" ref="cat"/>
        <property name="dog" ref="dog"/>
        <property name="name" value="wzh"/>
    </bean>
 
</beans>

输出:

一、在配置文件中装配bean

(一)byName

byName就是通过Bean的属性名称(id或name)自动装配。

实例:

1、修改xml配置,增加一个属性 autowire="byName":

    <bean id = "cat" class="com.hello.pojo.Cat"/>
    <bean id = "dog" class="com.hello.pojo.Dog"/>
    <bean id = "people" class="com.hello.pojo.People" autowire="byName">
        <property name="name" value="wzh"/>
    </bean>

此时测试成功

2、我们将 cat 的bean id修改为 catXXX

<bean id = "cat2" class="com.hello.pojo.Cat"/>

出现错误如下:

执行时报空指针java.lang.NullPointerException。因为按byName规则找不对应set方法,真正的setCat就没执行,对象就没有初始化,所以调用时就会报空指针错误。

小结:

 当一个bean节点带有 autowire byName的属性时。

(1)将查找其类中所有的set方法名,例如setCat,获得将set去掉并且首字母小写的字符串,即cat。

(2)去spring容器中寻找是否有此字符串名称id的对象。

(3)如果有,就取出注入;如果没有,就报空指针异常。

(二)byType

byName就是通过Bean的Class类型来自动装配。使用autowire byType首先需要保证:同一类型的对象,在spring容器中唯一。如果不唯一,会报不唯一的异常。

实例:

在xml配置再注册一个cat的bean对象:

    <bean id = "cat" class="com.hello.pojo.Cat"/>
    <bean id = "cat2" class="com.hello.pojo.Cat"/>
    <bean id = "dog" class="com.hello.pojo.Dog"/>
 
    <bean id = "people" class="com.hello.pojo.People" autowire="byType">
<!--        <property name="cat" ref="cat"/>-->
<!--        <property name="dog" ref="dog"/>-->
        <property name="name" value="wzh"/>
    </bean>

测试结果:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'people' defined in class path resource [beans.xml]: Unsatisfied dependency expressed through bean property 'cat'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.hello.pojo.Cat' available: expected single matching bean but found 2: cat,cat2

“NoUniqueBeanDefinitionException”,即bean定义不唯一。删掉其中一个cat的bean对象,将cat的bean名称改掉,则可测试成功,因为是按类型装配,所以并不会报异常,也不影响最后的结果。甚至将id属性去掉,也不影响结果。

二、使用注解实现自动装配

0、使用注解实现自动装配需要在xml配置文件中添加以下2个支持:

(1)在spring配置文件中引入context文件头

xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd

(2)开启属性注解支持!

<context:annotation-config/>

(一)@Autowired

  • @Autowired是按类型自动转配的,不支持id匹配。
  • 需要导入 spring-aop的包!

1、测试

(1)将People类中的set方法去掉,使用@Autowired注解

public class People {
    @Autowired
    private Cat cat;
    @Autowired
    private Dog dog;
    private String name;
 
    public Cat getCat(){
        return cat;
    }
 
    public Dog getDog(){
        return dog;
    }
 
  public String getName() {
        return name;
    }
}

此时ml配置文件:

	<context:annotation-config/>
    <bean id = "cat" class="com.hello.pojo.Cat"/>
    <bean id = "dog" class="com.hello.pojo.Dog"/>
 
    <bean id = "people" class="com.hello.pojo.People">
    </bean>

测试结果:

注:@Autowired(required=false) 说明对象可以为null;如果required=false,则对象必须存对象,不能为null。

(二)Qualifier

  • @Autowired是根据类型自动装配的,加上@Qualifier则可以根据byName的方式自动装配。
  • @Qualifier不能单独使用。

测试:

(1)配置文件修改内容,保证类型存在对象。且名字不为类的默认名字。

    <bean id = "cat1" class="com.hello.pojo.Cat"/>
    <bean id = "cat2" class="com.hello.pojo.Cat"/>
    <bean id = "dog1" class="com.hello.pojo.Dog"/>
    <bean id = "dog2" class="com.hello.pojo.Dog"/>

此时报错:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'people': Unsatisfied dependency expressed through field 'cat'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.hello.pojo.Cat' available: expected single matching bean but found 2: cat1,cat2

(2)在属性上添加Qualifier注解

    @Autowired
    @Qualifier(value = "cat2")
    private Cat cat;
    @Autowired
    @Qualifier(value = "dog2")
    private Dog dog;

测试测试成功。

(三)@Resource

  • @Resource如有指定的name属性,先按该属性进行byName方式查找装配;
  • 其次再进行默认的byName方式进行装配;
  • 如果以上都不成功,则按byType的方式自动装配。
  • 都不成功,则报异常。

测试:

public class People {
    @Resource(name = "cat2")
    private Cat cat;
    @Resource(name = "dog2")
    private Dog dog;
    private String name;
 
    public Cat getCat(){
        return cat;
    }
 
    public Dog getDog(){
        return dog;
    }
 
  public String getName() {
        return name;
    }
}

此时xml配置文件:

    <bean id = "cat1" class="com.hello.pojo.Cat"/>
    <bean id = "cat2" class="com.hello.pojo.Cat"/>
    <bean id = "dog1" class="com.hello.pojo.Dog"/>
    <bean id = "dog2" class="com.hello.pojo.Dog"/>

(2)实体类和xml配置文件:

public class People {
    @Resource
    private Cat cat;
    @Resource
    private Dog dog;
    private String name;
 
    public Cat getCat(){
        return cat;
    }
 
    public Dog getDog(){
        return dog;
    }
 
  public String getName() {
        return name;
    }
}

配置文件:

    <bean id = "cat1" class="com.hello.pojo.Cat"/>
    <bean id = "dog1" class="com.hello.pojo.Dog"/>

测试结果成功输出。

结论:

@Resource先进行byName查找,失败;再进行byType查找,成功。

小结:

@Autowired与@Resource异同

  • @Autowired与@Resource都可以用来装配bean。都可以写在字段上,或写在setter方法上。
  • @Autowired默认按类型装配(属于spring规范),默认情况下必须要求依赖对象必须存在,如果要允许null 值,可以设置它的required属性为false,如:@Autowired(required=false) ,如果我们想使用名称装配可以结合@Qualifier注解进行使用
  • @Resource(属于J2EE复返),默认按照名称进行装配,名称可以通过name属性进行指定。如果没有指定name属性,当注解写在字段上时,默认取字段名进行按照名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。
  • 它们的作用相同都是用注解方式注入对象,但执行顺序不同。@Autowired先byType,@Resource先byName。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • mybatis selectKey赋值未生效的原因分析

    mybatis selectKey赋值未生效的原因分析

    这篇文章主要介绍了mybatis selectKey赋值未生效的原因分析,selectKey 会将 SELECT LAST_INSERT_ID()的结果放入到传入的实体类的主键里面,文中通过代码示例给大家讲解非常详细,需要的朋友可以参考下
    2024-02-02
  • java多线程编程之向线程传递数据的三种方法

    java多线程编程之向线程传递数据的三种方法

    在多线程的异步开发模式下,数据的传递和返回和同步开发模式有很大的区别。由于线程的运行和结束是不可预料的,因此,在传递和返回数据时就无法象函数一样通过函数参数和return语句来返回数据
    2014-01-01
  • 通过java备份恢复mysql数据库的实现代码

    通过java备份恢复mysql数据库的实现代码

    这篇文章主要介绍了如何通过java备份恢复mysql数据库,其实一般情况下通过bat或sh就可以,这里主要是介绍了java的实现思路,喜欢的朋友可以参考下
    2013-09-09
  • Java synchronize底层实现原理及优化

    Java synchronize底层实现原理及优化

    这篇文章主要介绍了Java synchronize底层实现原理及优化,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03
  • SpringBoot 中大文件(分片上传)断点续传与极速秒传功能的实现

    SpringBoot 中大文件(分片上传)断点续传与极速秒传功能的实现

    这篇文章主要介绍了SpringBoot 中大文件(分片上传)断点续传与极速秒传功能的实现,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-07-07
  • JAVA中使用FileWriter写数据到文本文件步骤详解

    JAVA中使用FileWriter写数据到文本文件步骤详解

    这篇文章主要介绍了JAVA中使用FileWriter写数据到文本文件步骤详解,FileWriter类提供了多种写入字符的方法,包括写入单个字符、写入字符数组和写入字符串等,它还提供了一些其他的方法,如刷新缓冲区、关闭文件等,需要的朋友可以参考下
    2023-10-10
  • SpringCloud 中使用 Ribbon的方法详解

    SpringCloud 中使用 Ribbon的方法详解

    本文重点给大家介绍SpringCloud 中使用 Ribbon的方法,本文通过实例文字相结合的形式给大家介绍的非常详细,需要的朋友可以参考下
    2018-10-10
  • Spring @bean和@component注解区别

    Spring @bean和@component注解区别

    本文主要介绍了Spring @bean和@component注解区别,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • 解读nextLine().split(“[\\s]“)的意思

    解读nextLine().split(“[\\s]“)的意思

    这篇文章主要介绍了解读nextLine().split(“[\\s]“)的意思,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04
  • java之Thread不捕获异常默认处理逻辑

    java之Thread不捕获异常默认处理逻辑

    这篇文章主要介绍了java之Thread不捕获异常默认处理逻辑,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12

最新评论