Bean的自动装配

Posted 致非

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Bean的自动装配相关的知识,希望对你有一定的参考价值。

Bean的自动装配

  • 自动装配是使用spring满足bean依赖的一种方法
  • spring会在应用上下文中为某个bean寻找其依赖的bean。

Spring中bean有三种装配机制,分别是:

  1. 在xml中显式配置;
  2. 在java中显式配置;
  3. 隐式的bean发现机制和自动装配。

项目创建

一个人有两个宠物

Cat

package com.q.pojo;

public class Cat {
    public void shout(){
        System.out.println("Cat,喵喵");
    }
}

Dog

package com.q.pojo;

public class Dog {
    public void shout(){
        System.out.println("Dog,汪汪!!");
    }
}

People

package com.q.pojo;

import java.security.PrivateKey;

public class People {
    private Cat cat;
    private Dog dog;
    private String name;

    public People() {
    }

    public People(Cat cat, Dog dog, String name) {
        this.cat = cat;
        this.dog = dog;
        this.name = name;
    }

    @Override
    public String toString() {
        return "People{" +
                "cat=" + cat +
                ", dog=" + dog +
                ", name=\'" + 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;
    }
}

people.xml

byName:根据属性名自动装配,检查IoC容器并根据名字查找与属性完全一致的bean,并将其与属性自动装配。

因此bean的id只有为dog或者cat才能够被找到

byType:根据属性类型自动装配

  • 如果容器中存在一个与指定属性类型相同的bean,那么将与该属性自动装配
  • 如果存在多个该类型bean,那么抛出异常,并指出不能使用byType方式进行自动装配;
  • 如果没有找到相匹配的bean,则什么事都不发生
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="cat" class="com.q.pojo.Cat"></bean>

    <bean id="dog" class="com.q.pojo.Dog"></bean>

    <bean id="people" class="com.q.pojo.People">
        <property name="cat" ref="cat"></property>
        <property name="name" value="青岚"></property>
        <property name="dog" ref="dog"></property>
    </bean>
    <!--ByName 在上下文中查找,和自己set方法的后面的值一样-->
    <bean id="people1" class="com.q.pojo.People" autowire="byName">
        <property name="name" value="青岚"></property>
    </bean>

    <!--ByType 在上下文中查找相同类型注入  类型一致-->
    <bean id="people2" class="com.q.pojo.People" autowire="byType">
        <property name="name" value="青岚"></property>
    </bean>
</beans>

注解实现自动装配

@Autowired和@Resource的相同点:

都是用于自动装配的,都可以放在属性字段和set方法上
@Autowired和@Resource的区别:

@Autowired为Spring提供的注解,@Resource为java提供的注解
@Autowired 默认通过 byType 的方式实现,如果有多个对象,则通过 byName 查找,如果都找不到,则报错;此时可以用@Qualifier指定唯一的bean对象
@Resource 默认通过 byName 的方式实现,如果找不到名字, 则通过 byType 实现!如果两个都找不到,就会报错

要使用注解:

xml中导入约束

<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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
 

xml中配置注解支持

context:annotation-config/
1
@Autowired
直接在属性上使用即可,此时就可以省略set方法
也可以在set方法上使用(适用于在set方法里面写一些处理逻辑的情况)

beans.xml
context:annotation-config/

<bean id="cat1" class="pojo.Cat"/>
<bean id="dog1" class="pojo.Dog"/>
<bean id="people" class="pojo.People">
    <property name="name" value="zsr"/>
</bean>

运行测试类,成功

自动装配环境很复杂的情况下:假设此时有两个cat和dog对象

context:annotation-config/

<bean id="cat1" class="pojo.Cat"/>
<bean id="cat2" class="pojo.Cat"/>
<bean id="dog1" class="pojo.Dog"/>
<bean id="dog2" class="pojo.Dog"/>
<bean id="people" class="pojo.People">
    <property name="name" value="zsr"/>
</bean>

发现直接爆红了

这是因为无法匹配到对应的属性,@Autowired 默认通过 byType 的方式实现,如果有多个对象,则通过 byName 查找,如果都找不到,则报错;

此时通过有两个相同类型的对象,通过类型无法找到,bean id也不与属性名相同,通过名字也找不到,所以报错;

这时候就需要配合@Qualifier来使用,指定唯一的bean对象来注入

再次运行,即可成功

@Qualifier还可以设置required属性值为false 允许属性值为null

@Resource
我们将上述的Autowired换成Resource

xml文件为:

context:annotation-config/

<bean id="cat1" class="pojo.Cat"/>
<bean id="cat2" class="pojo.Cat"/>
<bean id="dog1" class="pojo.Dog"/>
<bean id="dog2" class="pojo.Dog"/>
<bean id="people" class="pojo.People">
    <property name="name" value="zsr"/>
</bean>

直接运行

发现报错了,这是因为我们无法匹配到对应的属性,@Resource 默认通过 byName 的方式实现,如果找不到名字, 则通过 byType 实现!如果两个都找不到,就会报错

此时,名字cat1/cat2/dog1/dog2不匹配,且每个类型的bean不唯一,所以通过名字和类型都找不到,因此报错

如果我们将其中一个bean的id改为对应的属性名cat和dog

再次运行,成功了

这是因为我们通过名字找到了
我们还有另一种解决方式,不用更改bean的id,我们在@Resource里面添加name属性

通过设置name属性指定装配的对象

此时再运行,成功注入


本文来自博客园,作者:致非,转载请注明原文链接:https://www.cnblogs.com/mycity/p/autowired.html

以上是关于Bean的自动装配的主要内容,如果未能解决你的问题,请参考以下文章

Spring5 Java代码装配Bean

spring:按照Bean的名称自动装配User

Spring5 自动化装配Bean

Spring基础:Bean自动装配

spring 自动装配 bean 有哪些方式?

Spring 实战-第二章-装配Bean