spring5.0 之依赖注入(Dependency Injection)

来源:互联网 发布:骨肉之躯 知乎 编辑:程序博客网 时间:2024/06/08 18:40

spring5.0 之依赖注入(Dependency Injection)

本系列博客使用spring boot目前最新版2.0.0.M2,对应spring 版本为Spring Framework 5.0.0.RC2。

 spring的依赖注入功能,主要体现了面向接口编程的思想及依赖反转(ioc)。

spring的依赖注入方式主要由:set方法注入和构造函数注入。

set方法注入会使对象的状态变更,在函数编式程中immutable objects非常流行,这时候我们就必须使用构造函数注入方式了,虽然有时候会使得构造函数的参数增多。

       set方法注入,一般情况下我们会使用对属性进行@Autowired注解,根据类型注入,从而省去了set方法。

      例如:

package org.sdcuike.demo.service.impl;import lombok.extern.slf4j.Slf4j;import org.sdcuike.demo.manager.DemoManager;import org.sdcuike.demo.service.BusinessService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import javax.annotation.PostConstruct;/** * Created by beaver on 2017/7/17. */@Service@Slf4jpublic class BusinessServiceImpl implements BusinessService {        @Autowired    private DemoManager demoManager;            @PostConstruct    public void init(){        log.info("set注入的类{}",demoManager);    }    }

为了验证demoManager实例被注入而非空指针,利用

@PostConstruct    public void init(){        log.info("set注入的类{}",demoManager);    }

应用启动后输出日志:

2017-07-17 22:25:28.735  INFO 27343 --- [           main] o.s.d.service.impl.BusinessServiceImpl   : set注入的类org.sdcuike.demo.manager.impl.DemoManagerImpl@55787112

    实例已被注入,当然DemoManager必须被spring自动扫描注入为前提:

package org.sdcuike.demo.manager.impl;import org.sdcuike.demo.manager.DemoManager;import org.springframework.stereotype.Component;/** * Created by beaver on 2017/7/17. */@Componentpublic class DemoManagerImpl implements DemoManager {}

@Autowired注解是类型注入,会从spring容器中找到同类型的对象实例,如果需要注入一个对象,spring容器中只有一个该类型的实例,此此实例就是我们需要的;如果spring容器中有多个该类型的实例,会报错误,比如:

创建两个int类型的实例:

package org.sdcuike.demo;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/** * Created by beaver on 2017/7/17. */@Configurationpublic class DemoConfig {        @Bean("integer1")    public Integer integer1() {        return 1;    }        @Bean("integer2")    public Integer integer2() {        return 2;    }}

    如果我们的注入方式为:

 @Autowired    private Integer integer;

   就会报以下给出的错误提示:



Description:Field integer in org.sdcuike.demo.service.impl.BusinessServiceImpl required a single bean, but 2 were found:- integer1: defined by method 'integer1' in class path resource [org/sdcuike/demo/DemoConfig.class]- integer2: defined by method 'integer2' in class path resource [org/sdcuike/demo/DemoConfig.class]Action:Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed

当然,我们的IntelliJ IDEA 很智能的给出错误提示,而无需运行:


 

如何解决呢,其实spring的错误日志也给予了提示:

Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed。

@Primary注解代表了注入的优先级,让@Primary注解的实例优先注入;@Qualifier注解主要是根据bean实例的name名来注入,所以我们需要对bean注解加上名字:@Bean("integer1")。

    @Autowired    @Qualifier("integer1")    private Integer integer;

         当然,根据实例名注入,我们可以使用标准注解:

 @Resource(name = "integer1")    private Integer integer;

     name的含义:

@Target({TYPE, FIELD, METHOD})@Retention(RUNTIME)public @interface Resource {    /**     * The JNDI name of the resource.  For field annotations,     * the default is the field name.  For method annotations,     * the default is the JavaBeans property name corresponding     * to the method.  For class annotations, there is no default     * and this must be specified.     */    String name() default "";

     name属性忽略,默认为field name或JavaBeans property name,如果默认的找不到,就按类型注入,其功能就退化为@Autowired注解的功能了。

    当然,set方法注入不常用,但set方法注入对与项目也是非常有用的,尤其注入集合类型。

    spring boot的主要免去了大量的配置,根据约定(如类路径下包含类判断是不是实例化)来初始化一些类的实例,但有时候实例化的类并不是我们需要的,但又排除不掉,这时候@Primary注解就很重要了。


   相关代码:https://github.com/sdcuike/Spring5-demo/tree/master/DependencyInjection





原创粉丝点击