web-dev-qa-db-ja.com

Spring Boot Annotation @Autowired of Serviceが失敗する

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アノテーションを削除し、次のようにAppConfigクラスにBeanとして追加すると、正常に機能します。

@Configuration
public class AppServiceConfig {

    public AppServiceConfig() {
    }

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

}

クラスは異なるパッケージにあります。 @ComponentScanを使用していません。代わりに、それを自動的に行う@SpringBootApplicationを使用しています。ただし、ComponentScanも試してみましたが、効果はありませんでした。

ここで何が悪いのですか?

8
drunkenfist

SpringのBeanを作成する方法は2つあります。あなたはそれらの1つを使う必要があるだけです。

  1. POJOを介した@Service

    _@Service
    public class SampleService
    _
  2. @Configurationアノテーションが必要な構成クラスの@Bean

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

@Autowiredはクラスタイプによって解決されるため、そのクラスタイプのBeanが1つしかない場合は@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クラスにコメントを付け、UserRepositoryとUserServiceがどのように自動接続されるかを確認できます。その後、各クラスの@Serviceのコメントを解除し、AppConfigとクラスのコメントを外します。

15
Eddú Meléndez