spring 错误百科
一、使用Spring出错根源
1、隐式规则的存在
你可能忽略了 Sping Boot 中 @SpringBootApplication 是有一个默认的扫描包范围的。这就是一个隐私规则。如果你原本不知道,那么犯错概率还是很高的。类似的案例这里不再赘述。
2、默认配置不合理
3、追求奇技淫巧
4、理所当然地使用
要完整接收到所有的 Header,不能直接使用 Map 而应该使用 MultiValueMap。
5、无关的依赖变动
你一定要意识到,当你的代码不变时,你的依赖变了,行为则可能“异常”了。
6、例如默认扫描 Bean 的范围、自动装配构造器等等
7、定义了多个构造器就可能报错,因为使用反射方式来创建实例必须要明确使用的是哪一个构造器
8、当一个单例的 Bean,使用 autowired 注解标记其属性时,你一定要注意这个属性值会被固定下来。
解决方案:
解决方案一:自动注入 Context
即自动注入 ApplicationContext,然后定义 getServiceImpl() 方法,在方法中获取一个新的 ServiceImpl 类型实例。修正代码如下:
@RestController
public class HelloWorldController {@Autowiredprivate ApplicationContext applicationContext;@RequestMapping(path = "hi", method = RequestMethod.GET)public String hi(){return "helloworld, service is : " + getServiceImpl();};public ServiceImpl getServiceImpl(){return applicationContext.getBean(ServiceImpl.class);}}
解决方案二: 使用 Lookup 注解
@RestController
public class HelloWorldController {@RequestMapping(path = "hi", method = RequestMethod.GET)public String hi(){return "helloworld, service is : " + getServiceImpl();};@Lookuppublic ServiceImpl getServiceImpl(){return null;} }
二、找不到合适的 Bean,但是原因却不尽相同。
1、提供的 Bean 过多又无法决策选择谁;
解决方案:精确匹配
@Autowired
DataService oracleDataService;
2、是因为指定的名称不规范导致引用的 Bean 找不到。
解决方案:定义处显式指定 Bean 名字,我们可以保持引用代码不变,而通过显式指明 CassandraDataService 的 Bean 名称为 CassandraDataService 来纠正这个问题。
@Repository("CassandraDataService")
@Slf4j
public class CassandraDataService implements DataService {//省略实现
}
3、引用内部类的 Bean 遗忘类名
解决方案:全部名称引入
@Autowired
@Qualifier("studentController.InnerClassDataService")
DataService innerClassDataService;
4、 @Value 不仅可以用来注入 String 类型,也可以注入自定义对象类型。同时在注入 String 时,你一定要意识到它不仅仅可以用来引用配置文件里配置的值,也可能引用到环境变量、系统参数等。
5、我们了解到集合类型的注入支持两种常见的方式,即上文中我们命名的收集装配式和直接装配式。这两种方式共同装配一个属性时,后者就会失效。
解决方案:只用一个
直接装配
@Bean
public List<Student> students(){Student student1 = createStudent(1, "xie");Student student2 = createStudent(2, "fang");Student student3 = createStudent(3, "liu");Student student4 = createStudent(4, "fu");return Arrays.asList(student1,student2,student3, student4);
}