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

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
@Slf4j
public 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.
 */
@Component
public 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.
 */
@Configuration
public 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 很智能的给出错误提示,而无需运行:

spring5.0 之依赖注入(Dependency Injection)_第1张图片

 

如何解决呢,其实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





你可能感兴趣的:(Spring,Boot,Spring,Boot,实战)