【问题标题】:NoSuchBeanDefinitionException when the package is changed from hello to foo.当包从 hello 更改为 foo 时出现 NoSuchBeanDefinitionException。
【发布时间】:2014-05-26 08:45:48
【问题描述】:

当我按照https://spring.io/guides/gs/spring-boot/ 提供的说明进行操作时,我可以让 Spring Boot 示例程序成功运行。

如果我将 HelloService 和 HelloServiceImpl(如下所示的代码)添加到 hello 包中并更改 HelloController.java 以调用 sayHello 方法,它会按预期工作,并且从 http://localhost:8080 开始,我会按预期看到下面显示的消息。

来自 Spring Boot 的问候! helloService = 来自 HelloServiceImpl 的问候

现在,如果我将 HelloService 和 HelloServiceImpl 移动到 foo 包中,然后在编译后运行它,我会收到如下所示的错误。

为什么 spring boot/framework 无法从 'foo' 包中获取所需的 bean?不过,我能够验证它是否可以从 hello 包中成功获取 bean。

谢谢,

cat HelloService.java

package hello;

public interface HelloService {

    public String sayHello();   

}

cat HelloServiceImpl.java

package hello;
import org.springframework.stereotype.Service;


@Service("helloService")
public class HelloServiceImpl implements HelloService {

    /* (non-Javadoc)
     * @see com.apress.prospring3.springblog.service.HelloService#sayHello()
     */
    @Override
    public String sayHello() {
        return "Hello  from HelloServiceImpl ";
    }

}

在HelloController.java中,将index方法中的return语句修改如下,调用hello服务。

cat HelloController.java

package hello;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
public class HelloController {

    @Autowired 
    private HelloService helloService;

    @RequestMapping("/")
    public String index() {
        return "Greetings from Spring Boot! helloService = " + helloService.sayHello();
    }
}

当我运行如下所示的命令时,没有错误。

$ java -jar 目标/gs-spring-boot-0.1.0.jar

$java-版本

java version "1.8.0"
Java(TM) SE Runtime Environment (build 1.8.0-b132)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b70, mixed mode)

$哪个java

/usr/bin/java

$ ls -lt /usr/bin/java

lrwxr-xr-x 1 根轮 74 Mar 9 22:00 /usr/bin/java -> /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java

如果我将 HelloService.java 和 HelloServiceImpl.java 从 hello 包移动到 foo 包并且没有其他更改,当我尝试运行它时会出现以下错误。当它可以从 hello 包中成功获取时,为什么它无法从 'foo' 包中获取?如何解决这个问题?这是否意味着这两个类必须驻留在 hello 包中才能工作?

谢谢,

java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:53)
    at java.lang.Thread.run(Thread.java:744)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'helloController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private foo.HelloService hello.HelloController.helloService; nested exception is org.springframework.beans.factory.**NoSuchBeanDefinitionException**: No qualifying bean of type [foo.HelloService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:292)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1180)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:300)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:296)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:660)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:552)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:293)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:749)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:738)
    at hello.Application.main(Application.java:17)
    ... 6 more

原因:org.springframework.beans.factory.BeanCreationException:无法自动装配字段:private foo.HelloService hello.HelloController.helloService;嵌套异常是 org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type of [foo.HelloService] found for dependency: 预计至少有 1 个 bean 有资格作为此依赖项的自动装配候选者。依赖注解:{@org.springframework.beans.factory.annotation.Autowired(required=true)} 在 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:508) 在 org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87) 在 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289) ... 22 更多 原因:org.springframework.beans.factory.NoSuchBeanDefinitionException:没有为依赖项找到类型为 [foo.HelloService] 的合格 bean:预计至少有 1 个 bean 有资格作为此依赖项的自动装配候选者。依赖注解:{@org.springframework.beans.factory.annotation.Autowired(required=true)} 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1060) 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:920) 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:815) 在 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:480) ... 24 更多

【问题讨论】:

    标签: spring spring-boot


    【解决方案1】:

    最初当 HelloService 在 hello 包中时,Configuration 类上的@ComponentScan 告诉 Spring 在 hello 包中查找其他组件、配置和服务,使其能够找到此类。 现在,由于您已将 HelloService 移至 foo 包,@ComponentScan 无法再找到它;您还需要指定新的包名称,例如:

        @ComponentScan({"hello","foo"})
    

    【讨论】:

    • 感谢 Application.java,如果我将 @ComponentScan 更改为您显示的内容,我可以验证我可以从命令行成功运行应用程序,没有错误。但是,当我转到下面显示的 URL 时,我得到了一个不同的错误 :-(。从 localhost:8080,错误是 Whitelabel 错误页面。此应用程序没有显式映射 /error,因此您将其视为后备。
    • 控制台上应该有一个堆栈跟踪,以便您查看发生了什么。由于现在这是一个不同的问题,我建议一个新线程。
    • 谢谢戴夫。控制台上没有错误。经过更多调查,当@ComponentScan注释语句中指定basePackageClass时,我能够验证spring依赖注入机制能够从另一个包中获取类,如下所示。
    • @ComponentScan(basePackageClasses = { HelloService.class, ApplicationService.class }) 。对我来说重要的一点是,我需要将所有与组件相关的类保存在某个包中,比如“hello”,然后用最少的代码行,spring 依赖注入机制能够将它们组合在一起。如果我必须跨越包之间的边界,首先我需要问我为什么要这样组织代码,如果绝对需要,那么在 @ComponentScan 注释中指定 basePackageClasses。谢谢,这个问题可以标记为已回答,感谢 Prakash 和 Dave。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-29
    • 1970-01-01
    • 2018-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多