Spring回顾——自动装配模式

Spring 支持五种自动装配模式:

  • byName模式:在使用byName模式进行自动装配时,Spring会尝试用每个属性去上下文中适配同名的bean,例如有一个TestInject bean,该bean中有一个私有属性 OmsGoodsVo 并且 我们在ApplicationContext中也定义了名为 OmsGoodsVo这个bean,那么在TestInject初始化时OmsGoodsVo这个bean将会被自动分配给TestInject中的OmsGoodsVo属性。

  • byType模式:在使用byType模式进行自动装配时,Spring会尝试在Spring上下文中取寻找相同类型的bean去分配给目标bean的对应属性。

  • 构造函数模式:该模式和byType模式有异曲同工之妙,该模式通过bean的构造器进行注入而不是通过setter ,在该模式下Spring总是会尝试进行构造器最大入参的适配,例如TestInjectbean有两个构造器分别是TestInject1(String,Integer) 和TestInject2(String) 如果在ApplicationContext上下文中同时存在一个String bean和 Integer bean,那么Spring总是会去使用TestInject1去进行注入。

  • 默认模式:Spring 将自动在构造函数模式和byType模式之间进行选择,选择的依据是如果bean存在一个默认的无参数构造函数则使用byType模式进行构造,否则用构造函数模式。

  • :不使用任何模式,这是Spring的默认设置


示例

有如下一个简单的配置文件:appliacation_test.xml, 我们将使用如下的bean来尝试不同的装配模式


<beans>

<bean id="omsGoodsVo"  class="com.biz.tower.vo.OmsGoodsVo"/>

<bean id="stockAllVo"  class="com.biz.tower.vo.StockAllVo"/>

<bean id="injectByType"  class="com.biz.tower.vo.TestInject"  lazy-init="true" 
 autowire="byType"/>

<bean id="injectByName"  class="com.biz.tower.vo.TestInject"  lazy-init="true" 
  autowire="byName"/>

<beanid="injectByConstructor"  class="com.biz.tower.vo.TestInject"  lazy-init="true"  autowire="constructor"/>

</beans>

在上面的配置中可以看见有两个空类 OmsGoodsVo 和 StockAllVo 并且同时命名为omsGoodsVo和stockAllVo ,同时有三个TestInject类来分别进行byTypebyNameconstructor的注入测试,设置lazy-init为true的目的是为了控制日志的打印位置并无其他作用

TestInject类:


/**

* @ClassName TestInject

* @Description 测试注入类

* @Author liuzhibo

* @Date 2019/2/28 11:00 PM

**/

public class TestInject{
 private OmsGoodsVo omsGoodsVoOne;
 private OmsGoodsVo omsGoodsVoTwo;
 private StockAllVo stockAllVo;

 public TestInject() {}
 
 public TestInject(OmsGoodsVo omsGoodsVo){
      System.out.println("单参数构造注入");
 }

 public TestInject(OmsGoodsVo omsGoodsVo,StockAllVo stockAllVo) {
      System.out.println("双参数构造注入");
 }
 
 public void setOmsGoodsVoOne(OmsGoodsVo omsGoodsVoOne) {
      System.out.println("属性装配-》set omsGoodsVoOne");
 }

 public void setOmsGoodsVoTwo(OmsGoodsVo omsGoodsVoTwo) {
      System.out.println("属性装配-》set omsGoodsVoTwo");
 }
 
 public void setStockAllVo(StockAllVo stockAllVo) {
      System.out.println("属性装配-》set stockAllVo");
 }

 public static void main(String[] args) {

   GenericXmlApplicationContext  ctx = new GenericXmlApplicationContext();
   ctx.load("classpath:/application_test.xml");
   ctx.refresh();
   
   TestInjecttestInject = null;
   System.out.println("----------------ByName 测试----------------");
   testInject = (TestInject) ctx.getBean("injectByName");

   System.out.println("----------------ByType 测试----------------");
   testInject = (TestInject) ctx.getBean("injectByType");

   System.out.println("----------------ByConstructor 测试----------------");
   testInject = (TestInject) ctx.getBean("injectByConstructor");
  }
}

在上面这段代码中,可以看到TestInject类拥有三个构造函数和三个私有属性以及对应的setter方法和一个main方法,我们将通过getBean的方式来分别触发byName,byType,byConstructor注入模式。

运行结果:

----------------ByName测试----------------

属性装配-》set stockAllVo

----------------ByType测试----------------

属性装配-》set omsGoodsVoOne

属性装配-》set omsGoodsVoTwo

属性装配-》set stockAllVo

----------------ByConstructor测试----------------

双参数构造注入

可以看到byName模式下只自动注入了stockAllVo,这是符合我们期望的一个结果,因为在TestInject中只有stockAllVo能通过名称在ApplocationContext上下文中找到适配的bean,当使用byType模式时,spring自动装配了TestInject类中的所有三个属性,构造函数注入同样是符合期望的。


Spring自动装配的日常应用

相信大多数人都遇到过 org.springframework.beans.factory.NoSuchBeanDefinitionException或者org.springframework.beans.factory.UnsatisfiedDependencyException 这两个异常,该异常大多数是在通过@Autowired注入bean时Spring在上下文中发现了相同类型的bean从而不知道该如何选择装配导致的,所以,有没有思考过以下问题:

1.为什么@Service通常不会直接打在interface上?

2.@Autowired为什么会有一个@Qualifier 与其适配?@Resource呢?


参考书籍:
《Spring 5 高级编程》第五版

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 文章作者:Tyan博客:noahsnail.com 3.4 Dependencies A typical ente...
    SnailTyan阅读 4,199评论 2 7
  • 什么是Spring Spring是一个开源的Java EE开发框架。Spring框架的核心功能可以应用在任何Jav...
    jemmm阅读 16,542评论 1 133
  • 2.1 我们的理念是:让别人为你服务 IoC是随着近年来轻量级容器(Lightweight Container)的...
    好好学习Sun阅读 2,734评论 0 11
  • 参考W3C Spring教程 Spring致力于J2EE应用的各种解决方案,而不仅仅专注于某一层解决方案。可以说S...
    王侦阅读 1,183评论 0 6
  • 五天的情绪打卡,今天结束了。 第一天主题:愤怒; 第二天主题:焦虑; 第三天主题:委屈; 第四天主题:痛苦; 第五...
    心理咨询师萍阅读 215评论 0 1