扫描不到Bean的定义

image.png
Spring默认会扫描标记了@SpringBootConfiguration的类所在的包,向上图所示,Spring默认会扫描不到 controller,进而提示找不到Bean

修复方式:

  1. @SpringBootApplication
  2. //@ComponentScan("controller")
  3. @ComponentScans(value = {@ComponentScan("controller")})

使用 @ComponentScan 可以扫描到 controller,但是原先的默认扫描路径又会失效,一旦指定扫描其他的包,原来的默认扫描包就会被忽略,我们可以使用 @ComponentScans来指定多个扫描路径

Bean定义时隐式依赖错误

Parameter 0 of constructor in ** required a bean of type ‘java.lang.String’ that could not be found.
Consider defining a bean of type ‘java.lang.String’ in your configuration.
image.png

场景:

  1. @Service
  2. public class ServiceImpl {
  3. private String serviceName;
  4. public ServiceImpl(String serviceName){
  5. this.serviceName = serviceName;
  6. }
  7. }

Spring中,当我们把一个类定义成为**Bean** 后,如果再显示定义了构造器,那么这个Bean 在构造时会根据构造器参数去寻找对应的Bean, 上例中在构造 ServiceImpl 时根据参数回去寻找 类型为 String 的Bean, 然后通过**反射**构造出这个bean, 如果容器中没有提供name 为 serviceName 的bean,则会爆出上面的异常信息。
修复方式:显式提供一个 name为 serviceName的bean。

Spring中都是使用 **反射 ** 来构建 bean 的

  1. @Service
  2. public class ServiceImpl {
  3. private String serviceName;
  4. public ServiceImpl(String serviceName){
  5. this.serviceName = serviceName;
  6. }
  7. public ServiceImpl(String serviceName, String otherStringParameter){
  8. this.serviceName = serviceName;
  9. }
  10. }

这段代码看似正确,实际上当Spring 在通过反射构造 ServiceImpl 这个Bean 时,无法确定到底要调用哪个 构造器,只能尝试调用默认构造器,而默认构造器又不存在,所以这段代码不能正确运行。

原型Bean被固定的问题

  1. @Service
  2. @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
  3. public class ServiceImpl {
  4. }

按照如下方式使用

  1. @RestController
  2. public class HelloWorldController {
  3. //使用 @Autowired 标记属性
  4. @Autowired
  5. private ServiceImpl serviceImpl;
  6. @RequestMapping(path = "hi", method = RequestMethod.GET)
  7. public String hi(){
  8. return "helloworld, service is : " + serviceImpl;
  9. };
  10. }

@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)表明我们期望每次生成不同的 ServiceImpl 实例,但实际上运行多次得到的都是同一个对象

当一个单例的bean, 使用 @Autowired 注解标记其属性时,这个属性值会被固定下来

修复方式一

  1. @RestController
  2. public class HelloWorldController {
  3. @Autowired
  4. private ApplicationContext applicationContext;
  5. @RequestMapping(path = "hi", method = RequestMethod.GET)
  6. public String hi(){
  7. return "helloworld, service is : " + getServiceImpl();
  8. };
  9. public ServiceImpl getServiceImpl(){
  10. return applicationContext.getBean(ServiceImpl.class);
  11. }
  12. }

Spring依赖注入常见错误

过多赠予,无所适从 required a single bean, but 2 were found