本系列博客使用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);
}
}
@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 {
}
创建两个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
如何解决呢,其实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;
@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 "";
当然,set方法注入不常用,但set方法注入对与项目也是非常有用的,尤其注入集合类型。
spring boot的主要免去了大量的配置,根据约定(如类路径下包含类判断是不是实例化)来初始化一些类的实例,但有时候实例化的类并不是我们需要的,但又排除不掉,这时候@Primary注解就很重要了。
相关代码:https://github.com/sdcuike/Spring5-demo/tree/master/DependencyInjection