【问题标题】:Spring Boot Annotation @Autowired of Service failsSpring Boot Annotation @Autowired of Service 失败
【发布时间】:2015-06-30 17:31:08
【问题描述】:

我正在尝试对 Spring Boot 应用程序中的 Service 类使用 @Autowired 注释,但它不断抛出 No qualifying bean of type 异常。但是,如果我将服务类更改为 bean,那么它可以正常工作。这是我的代码:

package com.mypkg.domain;
@Service
public class GlobalPropertiesLoader {

    @Autowired
    private SampleService sampleService;        
}

package com.mypkg.service;
@Service
public class SampleService{

}

这是我的 SpringBoot 类:

package com.mypkg;

import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;

@SpringBootApplication
@EnableJpaRepositories
@Import(RepositoryRestMvcConfiguration.class)
@EnableTransactionManagement
public class TrackingService {
    private static final Logger LOGGER = LoggerFactory.getLogger(TrackingService.class);

    static AnnotationConfigApplicationContext context;

    public static void main(String[] args) throws Exception {
        SpringApplication.run(TrackingService.class, args);
        context = new AnnotationConfigApplicationContext();
        context.refresh();
        context.close();

    }

}

当我尝试运行它时,我得到以下异常:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.mypkg.service.SampleService] 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)}

但是当我从 SampleService 类中删除 @Service 注释并将其作为 bean 添加到我的 AppConfig 类中时,它可以正常工作:

@Configuration
public class AppServiceConfig {

    public AppServiceConfig() {
    }

    @Bean(name="sampleService")
    public SampleService sampleService(){
        return new SampleService();
    }

}

这些类位于不同的包中。我没有使用@ComponentScan。相反,我使用的是@SpringBootApplication,它会自动执行此操作。但是,我也尝试使用 ComponentScan,但没有帮助。

我在这里做错了什么?

【问题讨论】:

  • 你能展示你的Application 类(使用main 方法的那个)吗?
  • 我已经用主类的代码更新了我的问题。
  • @drunkenfist 为什么要关闭上下文?你知道它会破坏所有的豆子仪式。
  • @drunkenfist 起初我无法重现此问题,使用与您发布的代码几乎相同的代码。然后在某个阶段,我意识到当我添加@Service 注释并点击快速导入时,我有两个选择。所以有一个 second @Service 来自我在我的 pom 中的一些依赖,在这种情况下是 spring-boot-starter-jersey 但可能还有其他的。这听起来很遥远,但您能检查一下您的 @Service 的确切导入吗?
  • 我输入了一个类似的例子,一切都很完美。如上所述,您可以检查您导入的 @Service 注释的完全限定包名称吗?

标签: spring spring-mvc annotations spring-boot


【解决方案1】:

您正在使用两种方法来构建 Spring 的 bean。您只需要使用其中之一即可。

  1. @Service 通过 POJO

     @Service
     public class SampleService
    
  2. @Bean在配置类中,必须用@Configuration注解

     @Bean
     public SampleService sampleService(){
         return new SampleService();
     }
    

@Autowired 由类类型解析,如果您只有一个具有该类类型的 bean,则不需要 @Bean(name="sampleService")

编辑 01

包 com.example

@SpringBootApplication
public class Application implements CommandLineRunner {

    public static void main(String... args) {
        SpringApplication.run(Application.class);
    }

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private UserService userService;

    @Override
    public void run(String... strings) throws Exception {
        System.out.println("repo " + userRepository);
        System.out.println("serv " + userService);
    }
}

包 com.example.config

@Configuration
public class AppConfig {

    @Bean
    public UserRepository userRepository() {
        System.out.println("repo from bean");
        return new UserRepository();
    }

    @Bean
    public UserService userService() {
        System.out.println("ser from bean");
        return new UserService();
    }
}

包 com.example.repository

@Service
public class UserRepository {

    @PostConstruct
    public void init() {
        System.out.println("repo from @service");
    }
}

包 com.example.service

@Service
public class UserService {

    @PostConstruct
    public void init() {
        System.out.println("service from @service");
    }

}

使用此代码,您可以注释AppConfig 类,然后您将看到UserRepositoryUserService 是如何自动连接的。在每个类中评论 @Service 并取消评论 AppConfig 之后,类也将自动装配。

【讨论】:

  • 我认为你的问题弄错了。我只使用其中一种方法。当我在 POJO 上用 @Service 注释它时,它失败了。但是当我在我的配置类中使用@Bean 时,它可以工作。我想知道为什么@Service 方式会失败。
  • 我已经更新了答案。静态 AnnotationConfigApplicationContext 上下文;用来? spring boot 管理生命周期,所以不确定你为什么使用 context.refresh() 和 context.close()
  • 对我来说,@Service 方法不起作用。只有声明为 @Bean 时才会获取。
  • 我使用的是 spring-boot 1.2.3.RELEASE。您使用的是哪个版本?你是用我的例子还是两者兼而有之?
  • 我有同样的问题,我使用的是 spring-boot 1.4.2.RELEASE。它在我使用 @Bean(name="sampleService") 时有效,但在我仅使用 @Bean 时无效
猜你喜欢
  • 1970-01-01
  • 2021-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-08
  • 2014-12-15
  • 1970-01-01
  • 2016-11-23
相关资源
最近更新 更多