Spring IoC-依赖注入与属性装配(1)-自动装配

概述

Spring容器能够通过检查ApplicationContext中的内容来实现依赖自动装配.

自动转配的模式

Spring IoC定义了几种装配模式可供选择:

模式解释
no不开启自动装配
byName通过名称自动装配, 在容器中查找名称然后装配
byType通过类型自动装配, 容器在内部查找匹配的类型进行自动装配, 如果存在多个会引发致命错误, 如果不村子一个则不会报错
constructor通过构造函数自动装配, 和byType类似, 如果不存在bean, 则会报错

自动装配示例

使用注解方式实现自动装配, 首先需要对Bean的类标注@Component或则类似注解来指示Spring IoC这是一个可以由Spring容器管理的Bean的类. 再在需要注释的构造函数或者字段或则setter方法上标注@Autowired注解来实现自动注入.

简单示例

@Component
public class Keyboard {
    private String name;

    public Keyboard() { }

    public Keyboard(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Keyboard{" +
                "name='" + name + '\'' +
                '}';
    }
}

@Component
public class Computer {
    private Keyboard keyboard;

    @Autowired
    public Computer(Keyboard keyboard) {
        this.keyboard = keyboard;
    }

    @Override
    public String toString() {
        return "Computer{" +
                ", keyboard=" + keyboard +
                '}';
    }
}

public class DIDemo {
    public static void main(String[] args) {
        String scanPackages = "lab.anoper.ioc.di.computer.component";
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(scanPackages);
        Computer computer = context.getBean("computer",
                lab.anoper.ioc.di.computer.component.Computer.class);
        System.out.println(computer);
    }
}

输出结果:

Computer{, keyboard=Keyboard{name='null'}}

多个同类型报错示例

java代码:

@Configuration
public class ComputerConfig {
    @Bean
    public Keyboard keyboard1() {
        return new Keyboard("keyboard1");
    }

    @Bean
    public Keyboard keyboard2() {
        return new Keyboard("keyboard2");
    }
}

@Component
public class Computer {
    private Keyboard keyboard;

    @Autowired
    public Computer(Keyboard keyboard) {
        this.keyboard = keyboard;
    }

    @Override
    public String toString() {
        return "Computer{" +
                ", keyboard=" + keyboard +
                '}';
    }
}

public class Keyboard {
    private String name;

    public Keyboard() { }

    public Keyboard(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Keyboard{" +
                "name='" + name + '\'' +
                '}';
    }
}

public class DIDemo {
    public static void main(String[] args) {
        String scanPackages = "lab.anoper.ioc.di.computer";
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(scanPackages);
        Computer computer = context.getBean("computer",
                lab.anoper.ioc.di.computer.component.Computer.class);
        System.out.println(computer);
    }
}

输出结果:

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'lab.anoper.ioc.di.computer.component.Keyboard' available: expected single matching bean but found 2: keyboard1,keyboard2
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'lab.anoper.ioc.di.computer.component.Keyboard' available: expected single matching bean but found 2: keyboard1,keyboard2

说明构造函数自动装配模式下, 当有超过一个同类型bean时候, 会报出致命错误.

  • 解决方案1: 修改代码, 使用@Primary注解标注一个主要的bean, 则可以成功.
@Configuration
public class ComputerConfig {
    @Bean
    @Primary
    public Keyboard keyboard1() {
        return new Keyboard("keyboard1");
    }

    @Bean
    public Keyboard keyboard2() {
        return new Keyboard("keyboard2");
    }
}
  • 解决方案2: 使用@Qualifier注解明确需要装配的bean的名称.
@Component
public class Computer {
    private Keyboard keyboard;

    @Autowired
    public Computer(@Qualifier("keyboard2") Keyboard keyboard) {
        this.keyboard = keyboard;
    }

    @Override
    public String toString() {
        return "Computer{" +
                ", keyboard=" + keyboard +
                '}';
    }
}

优缺点

优点:

  • 减少了属性配置或者是构造函数配置.
  • 在更新代码时候, 更懂更小, 不必更新依赖关系.

缺点:

  • 显式的申明总是会覆盖掉自动装配.
  • 不如显式装配精确.
  • 如果有同一个类型的多个值存在, 可能引发错误.

总结

使用@Autowired注解可以实现自动注入. 配置在属性字段名上使用setter方法注入, 配置在构造函数上将使用构造函数方式注入. 如果有个同类型的bean则会导致致命注入失败, 可以使用@Prmiary注解来确定一个主要组件, 或者在注入点使用@Qualifier来注明使用的bean的名字.

参考

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值