点击上方 Java学习之道,选择 设为星标

每天18点,干货准时奉上!

何为自动装配

自动装配是 Spring 满足 bean 依赖的一种方式。

在使用 Spring 配置 bean 时,我们都要给配置的 bean 的属性设置一个值,如果不手动设置则都是空。而自动的好处就在于,我们不用手动去设置一个值,spring 会在上下文中自动寻找并装配合适的值。

在 Spring 中有三种装配的方式:

  • 在 XML 中显示配置

  • 在 Java 代码中显示的配置

  • 隐式的自动装配

本文重点放在隐式自动装配的说明,手动装配的部分可以参照Spring对象如何创建与管理,又如何使用巧妙的方法注入属性呢?

环境

测试自动装配前,先来定义好三个 POJO 类,Cat、Dog、Person。并且有一个关系就是 Person 拥有狗和猫。

package com.javastudyway.pojo;
public class Cat {public void shout(){System.out.println("我是猫");}
}
package com.javastudyway.pojo;
public class Dog {public void shout(){System.out.println("I am Dog");}
}
package com.javastudyway.pojo;import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Person {/* 人有猫和狗 */private Cat cat;private Dog dog;private String name;/* getter/setter 和 toString */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;}@Overridepublic String toString() {return "People{" +"Cat = " + cat +", Dog = " + dog +", name = '" + name + '\'' +'}';}
}

Spring 配置文件部分:

<?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/beanshttps://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="cat" class="com.javastudyway.pojo.Cat"/><bean id="dog" class="com.javastudyway.pojo.Dog"/><bean id="person" class="com.javastudyway.pojo.Person"><property name="name" value="Java学习之道"/><property name="cat" ref="cat"/><property name="dog" ref="dog"/></bean>
</beans>

最后是测试类(MyTest):

import com.javastudyway.pojo.Person;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class MyTest {@Testpublic void test1(){ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");Person person = context.getBean("person", Person.class);person.getDog().shout();person.getCat().shout();}
}

测试普通装配的结果:装配没有问题。

配置实现自动装配

自动装配有三种方式:

  • byName

  • byType

  • constructor

在配置 bean 时,我们可以加入一个 「autowired」 属性,来使用自动装配。

byName

byName 通过匹配 bean 的 id是否跟 setter 对应,对应则自动装配。

意思就是说,如果我的 Person 中有一个 setCat() 而配置文件中有一个 「bean 的 id 为 cat」,则能够自动装配。

把刚刚手动装配方式的 bean 做一些修改,来演示自动装配:

<bean id="cat" class="com.javastudyway.pojo.Cat"/>
<bean id="dog" class="com.javastudyway.pojo.Dog"/>
<!--加上了 person 的 bean 的 autowired 属性并去掉了手动装配的 cat 和 dog -->
<bean id="person" class="com.javastudyway.pojo.Person" autowire="byName"><property name="name" value="Java学习之道"/>
</bean>

刚刚的测试类运行结果依旧正常,表明了自动装配的确是运行了。

如若我 bean 的 id 跟 setter 不对应呢?

<bean id="dog11" class="com.javastudyway.pojo.Dog"/>

把刚刚的 dog id改掉,其余不变再来测试:结果是出现了空指针异常,说明没有对象,也就反映出了自动装配失败了。

byType

byType 通过匹配 bean 中所需要的依赖类型在容器上下文中自动寻找装配。

byName 方式 dog11 自动装配失败了,那么 byType 呢?

稍稍改动一下 person,把自动装配方式改为 「byType」:

<bean id="person" class="com.javastudyway.pojo.Person" autowire="byType"><property name="name" value="Java学习之道"/>
</bean>

空指针异常不再出现,自动装配成功!

自动装配跟 id 无关?它真的还就没有关系,甚至在配置 cat 和 dog 这两个 bean 时不写 id 都不会报错。

但是 byType 的自动装配存在一个很严重的问题,因为不是通过唯一的 id 来匹配,而是通过类型来匹配,所以容器中不能存在多个相同类型的 bean。

这是官方文档中给出的自动装配的说明,Spring 官方也不是很支持使用 byType 来实现自动装配,使用唯一标识 id 来匹配也确实更为安全。

优异

byName 和 byType 也不能非说孰强孰弱,只是各有各的好处。

使用 byName 需要保证 bean 的 id 唯一,且这个 bean 需要自动注入的属性和set方法与 bean 的 id 要一致。

使用 byType 需要保证 bean 的 class 唯一,且这个 bean 需要自动注入的属性和类型要一致。

说到这里,对于自动装配也有一个初步的感悟,接下来就来使用「注解开发」的方式来实现自动装配。

使用注解实现自动装配

注解在 JDK1.5 之后被引入,而 Spring2.5 版本后也开始支持注解了。这些版本也都可以算得上远古版本,所以不用担心版本问题了。

关于使用注解还是 XML 官方给出了答案,使用注解比使用 XML 配置更好。

不多吹,下面开始演示注解。

使用注解的准备

使用注解我们还需要对原本的配置文件做一些修改:

  • 导入约束 导入约束,即增加 「context」 的约束。

  • 配置注解支持 在配置中加入 --  <context:annotation-config/>

<?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/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsd"><!-- 开启注解支持 --><context:annotation-config/><bean id="cat" class="com.javastudyway.pojo.Cat"/><bean id="dog" class="com.javastudyway.pojo.Dog"/><bean id="person" class="com.javastudyway.pojo.Person"/></beans>

这样一来,我们的配置文件就变得极度简洁了,剩下的事情全部都交给注解来搞定就行。

@AutoWired注解的使用

搞定了配置文件后就可以开始使用注解了,在 POJO 类需要自动装配的属性上加 @AutoWired 注解实现自动装配。

小贴士:

  • @AutoWired注解也可以在 setter 上使用;

  • 如果使用了 @AutoWired 注解,POJO 类中的 setter 方法也可以省略,因为自动装配注解是用反射来实现的。

@AutoWired 这个注解还有一个属性,required。来看看 @AutoWired 的源码:

public @interface Autowired {boolean required() default true;
}

「required」 的默认值为 true,那么,这个值的作用是什么呢?required -- 必需的,如果它的值为 true,则说明这个属性不是必需的(允许为null)。

import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
public class Person {/* * 如此声明 required 为 false,* 则该对象可以没有 cat 这个属性*/@Autowired(required = false)private Cat cat;@Autowiredprivate Dog dog;private String name;public Cat getCat() {return cat;}public Dog getDog() {return dog;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "People{" +"Cat = " + cat +", Dog = " + dog +", name = '" + name + '\'' +'}';}
}

@Qualifier

一般情况下,使用 @AutoWired 注解类似于 byType 的装配方式,但是如果我们在配置文件中,配置了同一个类的多个 bean,那么这时候 @AutoWired 该作何选择呢?

如果遇到这个情况我们就需要使用 @Qualifier 注解来辅助实现了。先来看看 @Qualifier 注解的源码:

public @interface Qualifier {String value() default "";
}

可以看到这个注解需要一个 value 的参数,这个参数即为我们要选择的 bean 的 id。

在配置文件中增加一个 dog 的 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"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsd"><!--开启注解的支持--><context:annotation-config/><bean id="cat" class="com.javastudyway.pojo.Cat"/><bean id="dog" class="com.javastudyway.pojo.Dog"/><bean id="dog2" class="com.javastudyway.pojo.Dog"/><bean id="person" class="com.javastudyway.pojo.Person" autowire="byType"><property name="name" value="Java学习之道"/></bean></beans>

再搭配上 @Qualifier 注解

import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;public class Person {@Autowired(required = false)private Cat cat;@Autowired@Qualifier(value = "dog2")private Dog dog;private String name;public Cat getCat() {return cat;}public Dog getDog() {return dog;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "People{" +"Cat = " + cat +", Dog = " + dog +", name = '" + name + '\'' +'}';}
}

这样便能在多个同类 bean 实现使用 @AutoWired 自动装配任意一个 bean。

@Resource

前文说到的两个注解皆是 Spring 的注解,在 Java 中还有一个原生注解,「@Resource」,这个注解的作用类似于 @AutoWired 和 @Qualifier的结合体。

在 bean 的自动装配情况下,可以使用到 @Resource 的 name 参数,这个 name 的参数相当于 @Qualifier 的 value 参数。

@Resource 与 @AutoWired 的不同在于:

  • @Resource 默认是按照 名称 来装配注入的,当找不到与名称匹配的 bean 才会按照类型来装配注入。

  • @Autowired 默认是按照 类型 装配注入的,如果想按照名称来装配注入,则需要结合 @Qualifier 一起使用;

将配置的两个 dog 改成 dog1 和 dog2,再来使用 「@Resource」 注解。

<bean id="dog1" class="com.javastudyway.pojo.Dog"/>
<bean id="dog2" class="com.javastudyway.pojo.Dog"/>
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;import javax.annotation.Resource;public class Person {@Resourceprivate Cat cat;@Resourceprivate Dog dog;private String name;public Cat getCat() {return cat;}public Dog getDog() {return dog;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "People{" +"Cat = " + cat +", Dog = " + dog +", name = '" + name + '\'' +'}';}
}

运行的结果为:

因为 @Resource 默认是通过 id 来查找 bean,而配置的两个 dog 的 bean 没有一个名称为默认查找的 dog,故而创建失败。

修改 @Resource,加入参数:

@Resource(name = "dog1")
private Dog dog;

重新测试结果:

因为能够通过 name 这个参数匹配到 Dog 类型的 bean,所以程序便不会出现问题。

@Resource总结

@Resource 注解默认通过 byName 匹配 bean,如果 id 匹配失败则会通过类型匹配,但是如果同个类型的 bean 不唯一或者该类的 bean 不存在则装配失败。

-- END --

 | 更多精彩文章 -


  • [图解] 再不怕 Spring 循环依赖!

  • 给我十分钟让你get Spring注解开发!!

  • Redis 实现轻量级搜索引擎, 绝对需要Get!!

  • Spring Bean的作用域以及注解使用

  • Redis内存爆满了怎么办?

《Java学习-进阶手册》

公众号后台回复「手册」获取资料

▽加我微信,交个朋友长按/扫码添加↑↑↑

万字详解! Spring Bean的自动装配相关推荐

  1. Spring精华问答 | Spring Bean的自动装配是怎么回事?

    戳蓝字"CSDN云计算"关注我们哦! Spring框架是由于软件开发的复杂性而创建的.Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情.然而,Sprin ...

  2. 请解释Spring Bean 的自动装配?

    在Spring 框架中,在配置文件中设定bean 的依赖关系是一个很好的机制,Spring 容器还可以自动装配合作关系bean 之间的关联关系.这意味着Spring 可以通过向Bean Factory ...

  3. Spring bean的自动装配

    配置bean 配置形式:基于xml文件的方式:基于注解的方式 bean的配置方式:通过全类名(反射),通过工厂方法(静态工厂方法和实例工厂方法),FactoryBean Car类 package co ...

  4. Spring——Bean的自动装配

    自动装配是Spring满足bean依赖的一种方式 Spring会在上下文中自动寻找,并自动给bean装配属性 Spring中有三种装配方式 1.在xml中显示的配置 2.在Java中显示的配置 3.隐 ...

  5. [Spring]Bean的自动装配

    Spring支持5种自动装配模式,如下: 1.no --默认情况下,不自动装配,通过"ref"attribute手动设定. 2.buName --根据Property的Name自动 ...

  6. Spring Bean的自动装配方式

    1.no:这是默认设置,表示没有自动装配.应使用显式 bean 引用进行装配. 2.byName:它根据 bean 的名称注入对象依赖项.它匹配并装配其属性与 XML文件中由相同名称定义的 bean. ...

  7. Spring之 Bean的自动装配

    什么是Spring Bean的自动装配? 自动装配是Spring满足bean依赖一种方式 Spring会在上下文种自动寻找,并自动给bean装配属性 Spring种有三种装配方式 1.在xml种显示配 ...

  8. java 自动装载_java_详解Java的Spring框架下bean的自动装载方式,Spring容器可以自动装配相互协 - phpStudy...

    详解Java的Spring框架下bean的自动装载方式 Spring容器可以自动装配相互协作bean之间的关系,这有助于减少对XML配置,而无需编写一个大的基于Spring应用程序的较多的和元素. 自 ...

  9. Spring核心组件详解(Bean、Context、Core)

    上篇文章介绍了Spring的有三个核心组件,它们为什么是Spring的核心组件,它们之间啥关系,都代表了啥角色. 下面将详细介绍每个组件内部类的层次关系,以及它们在运行时的时序顺序.我们在使用 Spr ...

最新文章

  1. ubuntu安装http server
  2. 上海交通大学乐经良高数手写笔记-多元微积分
  3. sqlserver yml配置文件
  4. shiro学习(1):shiro简介
  5. 张平文当选美国工业与应用数学学会会士
  6. 推动Windows的限制:虚拟内存
  7. 转载:【微信小程序】 wx:if 与 hidden(隐藏元素)区别
  8. 介词短语做后置定语(由of引导)
  9. network 一级,二级,子域名
  10. robotframework 新建UI自动化测试用例实例一(2)
  11. 可以运行的Oracle Advanced Queue的例子
  12. 信号与系统思维导图框图(更新)
  13. 推荐一个js脚本的字体拟合模型
  14. python零基础怎么学英语最快_零基础如何快速成为Python高手
  15. 【校招实习面试实战,身临其境】华为软件开发工程师面试复盘总结
  16. android 那个桌面好,Hola桌面 可能是最好用的安卓手机桌面
  17. 每分钟54万多条数据更新,商品系统性能如何优化?
  18. 稀疏存储矩阵 matlab,稀疏矩阵的数据结构_稀疏矩阵 matlab_稀疏矩阵存储格式总结+存储效率对比:COO,CSR,DIA,ELL,HYB...
  19. afx是什么意思呀,什么时候要include呢,这个头文件的作用是??
  20. 全球案例 | 一家有着百年历史的航空公司如何扩展和转型,推动航空业创新

热门文章

  1. Vue使用speak-tts插件实现后台管理系统语音播报功能
  2. Myeclipse 误删项目文件怎么恢复!
  3. 利用 MoviePy 实现 FLV 转 MP3
  4. 为什么很多学华为、阿里的公司,最后都死掉了?
  5. Dubbo之HTTP RPC vs Dubbo RPC性能压测
  6. Ubuntu Linux gcc的常用命令
  7. SPSS 24 64位安装
  8. 软件开发风险策略,需要重点关注几点。
  9. Visual Studio中JavaScript智能提示(即引用JS库)
  10. 圈1到圈50打不出来,直接复制