案例 1:过多赠予,无所适从
代码如下 :
@RestController
@Slf4j
@Validated
public class StudentController {
@Autowired
DataService dataService;
@RequestMapping(path = "students/{id}", method = RequestMethod.DELETE)
public void deleteStudent(@PathVariable("id") @Range(min = 1,max = 100) int id){
dataService.deleteStudent(id);
};
}
public interface DataService {
void deleteStudent(int id);
}
@Repository
@Slf4j
public class OracleDataService implements DataService{
@Override
public void deleteStudent(int id) {
log.info("delete student info maintained by oracle");
}
}
@Repository
@Slf4j
public class CassandraDataService implements DataService{
@Override
public void deleteStudent(int id) {
log.info("delete student info maintained by cassandra");
}
}
在启动这个Spring程序中报出了这样一个异常 :required a single bean, but 2 were found
这里IOC容器在根据接口注入属性时,得到了两个注入的bean组件,它是不知道注入哪个bean组件的。一没有给某个bean组件加优先级。二属性名没有按规则指定类名。
那么就可以根据这两个条件分别解决这个问题。示例代码如下:
@Repository
@Primary
@Slf4j
public class OracleDataService implements DataService{
//省略非关键代码
}
@Autowired
DataService oracleDataService;
案例 2:显式引用 Bean 时首字母忽略大小写
示例代码如下:
@Autowired
@Qualifier("CassandraDataService")
DataService dataService;
当运行程序时,会报这样一个异常 :nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.spring.puzzle.class2.example2.DataService' available: expected at least 1 bean which qualifies as autowire candidate.
作者开始学习Spring的时候就知道,显示注入bean首字母要小写,但如果是以下情况呢?示例代码如下:
@Autowired
// 定义了一个SQLiteDataService类
@Qualifier("sQLiteDataService")
DataService dataService;
确还是报了NoSuchBeanDefinitionException异常。
其实在注入bean组件的底层代码中,如果一个类名开头的两个字母都是大写,显式注入的名称则是类名,否则首字母小写。底层代码如下:
public static String decapitalize(String name) {
if (name == null || name.length() == 0) {
return name;
}
if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) &&
Character.isUpperCase(name.charAt(0))){
return name;
}
char chars[] = name.toCharArray();
chars[0] = Character.toLowerCase(chars[0]);
return new String(chars);
}