SpringBoot 依赖注入IoC和控制反转DI

Spring 最成功的是其提出的理念,而不是技术本身。它所依赖的两个核心理念,一个是控制反转(Inversion of Control,IoC),另一个是面向切面编程(Aspect Oriented Programming,AOP),本文将重点介绍 IoC 的两个关键功能装载 Bean 和 Bean 之间的依赖关系(依赖注入,Dependency Injection,DI)

Spring 最成功的是其提出的理念,而不是技术本身。它所依赖的两个核心理念,一个是控制反转(Inversion of Control,IoC),另一个是面向切面编程(Aspect Oriented Programming,AOP)

IoC 是一种通过描述来生成或者获取对象(Bean)的技术,这个技术不是 Spring 甚至不是 Java 独有的。平时最熟悉的是使用 new 关键字来创建对象,而在 Spring 中则不是,它是通过描述来创建对象。Spingt Boot 中建议使用注解描述生成对象而不是使用 XML。

Spring 中把每一个需要管理的对象称为 Spring Bean(简称 Bean),管理这些 Bean 的容器称为 Spring IoC 容器(或者简称 IoC 容器)。IoC 容器具备两个基本的功能:通过描述管理 Bean(包括发布和获取 Bean)和通过描述完成 Bean 之间的依赖关系。

Spring IoC 容器总,可以按类型(by type)或者按名称(by name)获取 Bean,默认情况下 Bean 都是以单例存在的。

IoC 装配 Bean

使用@Bean 注解装配 Bean

@Configurationpublic class BeanConfig {    @Bean(name = "user")    public User initUser() {        User user = new User();        user.setUsername("Jack");        user.setAge(18);        return user;    }}

@Configuration 表示这是一个 Java 配置文件,Spring 容器会根据它来生成 IoC 容器去装配 Bean@Bean 表示将 initUser 方法返回的 POJO 装配到 IoC 容器中,属性 name 定义 Bean 的名称,如果没有设置该属性,则默认使用方法名称 initUser 作为 Bean 的名称保存到 Spring IoC 容器中

通过扫描装配 Bean

如果使用@Bean 一个个的装配,将是一件很麻烦的事情,Spring 也意识到了这点,允许使用扫描的方式进行装配,使用的注解是@Component 和@ComponentScan,@Component 标明哪个类被扫描进入 Spring IoC 容器,而@ComponentScan 则是标明采用何种策略扫描装配 Bean

package com.test.example.config;@Component("user")public class User {    @Value("Jack")    private String username;    @Value("18")    private int age;  }

@Component 标明该类将被 Spring IoC 容器扫描装配,其中配置的 user 则是 Bean 的名称,如果不配置,则 IoC 容器默认会把类名第一个字母作为小写,其他不变作为 Bean 名称@Value 指定具体的值,使得 Spring IoC 给予对应的属性注入对应的值

为了 Spring IoC 容器装配这个类,调整 BeanConfig

package com.test.example.config;@Configuration@ComponentScanpublic class BeanConfig {}

@ComponentScan 标明会进行扫描,默认只是扫描 BeanConfig 所在的当前 package 和子 package,可以观察到 User 也在该 package 下面,但是这样设置太不合理,为了更加合理,运行@ComponentScan 扫描自定义的包

@ComponentScan(basePackages = {" com.test.example.pojo"})

包名可以采用正则表达式匹配,但是这个也有不合理的地方,比如不想加载某些 Bean,比如定义一个 UserService 类,将它标记为@Service(该注解已经注入了@Component)服务类,则也会被 Spring 扫描装配到 IoC 容器中,如果不希望这些服务类被装配,则可以通过设置 excludeFilters

@ComponentScan(basePackages = {" com.test.example.*", excludeFilters = {@Filter(classes = {Service.class})}})

由于加入 excludeFilters 设置,则使用@Service 注解的服务类不会被扫描注入

自定义第三方 Bean

实际项目中经常需要引入许多第三方的包,并且希望把第三方包的类对象放入到 Spring IoC 容器中,这时需要使用@Bean 注解

定义一个数据源

 @Bean(name = "dataSource") public DataSource getDataSource() {    Properties props = new Properties();    props.setProperty("driver", "com.mysql.jdbc.Driver");    props.setProperty("url", "jdbc:mysql://localhost:3306/test");    props.setProperty("username", "root");    props.setProperty("password", "root");    DataSource dataSource = null;    try {        dataSource = BasicDataSourceFactory.createDataSource(props);    } catch (Exception e) {        e.printStackTrace();    }    return dataSource; }

通过@Bean 的 name 配置 Bean 名称为“dataSource”,如果不设置 name 属性,默认会使用方法名称作为 Bean 名称保存到 IoC 容器中。

上半部分主要讨论了 Bean 如何装载到 IoC 容器中,对于如何获取以及 Bean 之间的依赖,在 Spring IoC 概念中称为依赖注入(Dependency Injection,DI)

依赖注入 DI

@Autowired

Spring 中最常用注解之一,可以标注属性、方法、参数。

根据类型(by type)获取 Bean,@Autowired 是一个默认必须找到对应 Bean 的注解,如果不确定其标注的属性一定存在并且允许被标注的属性为 Null,可以设置 required 属性为 false

@Autowired(require = false)

消除歧义性 @Primary 和@Qualifier

@Primary 是一个修改优先权的注解,其目的当发现有多个同类型的 Bean 时,高速 IoC 容器优先使用该注解标记的 Bean,但是它也可以被标注到多个 Bean 上,这时 IoC 容器还是无法区分要采用哪个 Bean 实例,此时需要使用@Qualifier 的 value 来进行设置

@Qualifier 和@Autowired 组合在一起就是通过类型和名称一起找到 Bean,Bean 的名称在 IoC 容器中是唯一的,如

@Autowired@Qualifier("dog")private Animal animal = null;

带有参数的构造方法类装配

public ConstructorAnimal(@Autowired @Qualifier("dog") Animal animal) {    ...}

阅读全文: http://gitbook.cn/gitchat/activity/5ea0102e37944038c075ed2c

您还可以下载 CSDN 旗下精品原创内容社区 GitChat App ,阅读更多 GitChat 专享技术内容哦。

FtooAtPSkEJwnW-9xkCLqSTRpBKX

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值