web-dev-qa-db-fra.com

Échec de l'annotation de démarrage de printemps @Autowired of Service

J'essaie d'utiliser @Autowired annotation pour une classe de service dans l'application Spring Boot, mais elle continue de lancer No qualifying bean of type exception. Cependant, si je change la classe de service en bean, cela fonctionne bien. Voici mon code:

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

    @Autowired
    private SampleService sampleService;        
}

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

}

Et voici ma classe 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();

    }

}

Lorsque j'essaie d'exécuter cela, j'obtiens l'exception suivante:

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)}

Mais quand je retire le @Service annotation de la classe SampleService, et ajoutez-la en tant que bean dans ma classe AppConfig comme ci-dessous, cela fonctionne très bien:

@Configuration
public class AppServiceConfig {

    public AppServiceConfig() {
    }

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

}

Les classes sont dans des packages différents. Je n'utilise pas @ComponentScan. Au lieu de cela, j'utilise @SpringBootApplication qui le fait automatiquement. Cependant, j'ai également essayé avec ComponentScan mais cela n'a pas aidé.

Qu'est-ce que je fais mal ici?

8
drunkenfist

Vous utilisez deux méthodes pour créer un bean Spring. Vous avez juste besoin d'en utiliser un.

  1. @Service sur le POJO

    @Service
    public class SampleService
    
  2. @Bean dans la classe de configuration qui doit être annotée avec @Configuration

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

@Autowired est résolu par le type de classe, alors @Bean(name="sampleService") n'est pas nécessaire si vous n'avez qu'un seul bean avec ce type de classe.

EDIT 01

package 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);
}
}

package 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();
}
}

package com.example.repository

@Service
public class UserRepository {

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

package com.example.service

@Service
public class UserService {

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

}

En utilisant ce code, vous pouvez commenter la classe AppConfig, puis vous verrez comment UserRepository et UserService sont câblés automatiquement. Après ce commentaire, @Service dans chaque classe et décommentez AppConfig et les classes seront également câblés automatiquement.

15
Eddú Meléndez