Spring ---- Bean的自动装配

前言

自动装配是Spring满足bean依赖的一种重要方式,它是通过IOC容器在上下文中自动寻找,并自动给bean装配属性的一个过程。

1. 隐式的自动装配bean

在Spring官方文档的描述中,对于装配共有三种方式:

  • 在xml中显示的配置 (简单来说就是在.xml中通过property和value进行赋值)
<bean id = "hello" class="com.gs.pojo.Hello">
   <property name="str" value="Spring"/>
</bean>
  • 在java中通过代码进行显示配置(使用的比较少)
  • 隐式的自动配置bean(这里有两种形式,一种是在xml通过byType,byName实现,一种是在java类中通过@Autowired等注解实现)

最后一种最为重要,也较为方便。通过一个具体实例来说明这两种实现形式的用法

1.1 在xml上实现隐式自动装配

[1] 创建实体类(三个实体类,一个人和两只宠物)
最终的环境为:
在这里插入图片描述
Cat.java

package com.gs.pojo;
public class Cat {
    public void shout(){
        System.out.println("miao~");
    }
}

Dog.java

package com.gs.pojo;
public class Dog {
    public void shout(){
        System.out.println("wang~");
    }
}

Person.java (一个人拥有一只猫和一条狗)

package com.gs.pojo;

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.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;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", cat=" + cat +
                ", dog=" + dog +
                '}';
    }
}

[2] 导入Maven依赖(一个Spring的相关包,一个测试包)

  <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
        </dependency>
    </dependencies>

[3] 编写beans.xml 进行实体类的装配(即我们之前用的new实体类)

  • 通过ByName进行装配
<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
   <bean id="cat" class="com.gs.pojo.Cat"/>
   <bean id="dog" class="com.gs.pojo.Dog"/>
	
	<!--通过autowired的byName进行名字的查找装配,这时dog和cat已经装配进实体类Person中了-->
	<bean id = "person" class="com.gs.pojo.Person" autowire="byName">
	    <property name="name" value="gs"/>
	</bean>
</beans>
  • 通过ByType进行自动装配(开头文件与上面一致,下面就不再重复了)
<bean class="com.gs.pojo.Cat"/>
<bean class="com.gs.pojo.Dog"/>

 <!--byName: 会自动在容器上下文中查找,和自己对象set方法名字相同的bean id
     byTape: 会自动在容器上下文中查找,和自己对象set方法类型相同的class
 -->
<bean id = "person" class="com.gs.pojo.Person" autowire="byType">
    <property name="name" value="gs"/>
</bean>

两种形式分别进行测试

import com.gs.pojo.Person;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {

    @Test
    public void test1(){
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

        Person person = context.getBean("person", Person.class);
        person.getDog().shout();
        person.getCat().shout();

    }
}

在这里插入图片描述
很明显,我们通过ByType和ByName替代了我们之前使用的property和value(ref)的操作,这里我们通过类型和名字进行了相关实体类的自动装配。

小结:

  • 使用byName的时候,需要保证所有的bean的id唯一,并且这个bean id需要和我们自己set对象属性名一致
    就如:Person类中的属性名cat和bean中的id值一致。
  • 使用byType的时候,需要保证所有的bean的clsaa唯一,并且这个bean class需要和自己set对象属性的类型一致
1.2 使用注解实现自动装配

关于测试环境的搭建和上面一致
区别点:
在使用注解时需要在beans.xml中导入约束 (context约束)
在beans.xml中配置注解的支持

 <context:annotation-config/>

所以我们对上面的beans.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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

   <!--开启注解-->
   <context:annotation-config/>
    <bean id="cat" class="com.gs.pojo.Cat"/>
   <bean id="dog" class="com.gs.pojo.Dog"/>
   <bean id = "person" class="com.gs.pojo.Person" />
</beans>

[1] 使用@Autowired对属性进行装配

  • @Autowired是按照类型进行匹配的,它可以直接在属性上使用,也可以在set方式上使用
  • 使用@Autowired我们可以不编写set方法,但前提是这个自动装配的属性在IOC容器中已经存在了,且符合byType,没有在beans.xml中配置多个相同类型

在Person中使用: (这样就是现了cat和dog两个属性的装配了)

public class Person {
    private String name;
    @Autowired
    private Cat cat;
    @Autowired
    private Dog dog;

这个代码的测试和上面的结果一致

[2] 对于在beans.xml中配置了多个相同类型的实体类时,由于@Autowired是根据类型查找,由于类型一致,且有多个,那么它在匹配时会产生混乱,这时候需要结合@Qualifer(value=“xxx”)来指定名字进行相关装配
beans.xml中(这是存在多个cat)

<bean id="cat1" class="com.gs.pojo.Cat"/>
<bean id="cat2" class="com.gs.pojo.Cat"/>
<bean id="dog" class="com.gs.pojo.Dog"/>
<bean id = "person" class="com.gs.pojo.Person" />

装配时

public class Person {

    private String name;
    @Autowired
    @Qualifier(value = "cat1")
    private Cat cat;
    @Autowired
    private Dog dog;

[3] 上面都是通过类型进行装配的,那么什么注解是通过名字进行装配呢?在java注解中@Resource很好的诠释了这一点,这个注解可以说是@Autowired和@Qualifer的结合。
@Resource默认是按照名称进行装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入
beans.xml

<bean id="cat" class="com.gs.pojo.Cat"/>
 <bean id="cat2" class="com.gs.pojo.Cat"/>
<bean id="dog" class="com.gs.pojo.Dog"/>
<bean id = "person" class="com.gs.pojo.Person" /> 

装配:(这时是可以完美匹配的,因为cat在beans.xml中能找到)

public class Person {
    private String name;
    @Resource
    private Cat cat;
    @Autowired
    private Dog dog;

那我们该一下bean.xml的内容(这时候没有cat这个属性名)

<bean id="cat1" class="com.gs.pojo.Cat"/>
 <bean id="cat2" class="com.gs.pojo.Cat"/>
<bean id="dog" class="com.gs.pojo.Dog"/>
<bean id = "person" class="com.gs.pojo.Person" />

我们原来装配的代码就会报错了,为什么呢?
在上面我们说过@Resource默认是按名字匹配的,如果找不到可以按类型匹配,那么我们没有cat这个名字,此时类型又有两个是一致的,那么它的匹配又会出现混乱,这是我们可以通过@Resource(name=“xxx”)来指定装配的名字

public class Person {

    private String name;
    @Resource(name = "cat1")
    private Cat cat;
    @Autowired
    private Dog dog;

@Resource和@Autowired的异同:

  1. 都是用来装配的,都可以放在属性字段上
  2. @Autowired是通过byType方法实现的,而且必须要求这个对象存在
  3. @Resource默认是通过byName的方式实现的,如果找不到名字,则通过byType来实现,如果两个都找不到就会报错。
  4. @Autowired是Spring上的注解,@Resource是Java上的注解

一天一句鼓励自己的话,即使再小的帆也能远航 。 -----出自最喜欢的UP主狂神

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值