Dans Spring normal, lorsque nous voulons câbler automatiquement une interface, nous définissons son implémentation dans le fichier de contexte Spring. Et Spring Boot? Comment pouvons-nous y parvenir? actuellement, nous n'autorisons que les classes qui ne sont pas des interfaces. Une autre partie de cette question concerne l'utilisation d'une classe dans une classe Junit à l'intérieur d'un projet de démarrage Spring. Si nous voulons utiliser un CalendarUtil par exemple, si nous câblons automatiquement CalendarUtil, il lèvera une exception de pointeur nul. Que pouvons-nous faire dans ce cas? Je viens d'initialiser en utilisant "nouveau" pour l'instant ...
Utilisation @Qualifier
l'annotation est utilisée pour différencier les beans de la même interface
Jetez un œil à Spring Boot documentation
De plus, pour injecter tous les beans de la même interface, juste autowire List
de l'interface
(De la même manière dans Spring/Spring Boot/SpringBootTest)
Exemple ci-dessous:
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
public interface MyService {
void doWork();
}
@Service
@Qualifier("firstService")
public static class FirstServiceImpl implements MyService {
@Override
public void doWork() {
System.out.println("firstService work");
}
}
@Service
@Qualifier("secondService")
public static class SecondServiceImpl implements MyService {
@Override
public void doWork() {
System.out.println("secondService work");
}
}
@Component
public static class FirstManager {
private final MyService myService;
@Autowired // inject FirstServiceImpl
public FirstManager(@Qualifier("firstService") MyService myService) {
this.myService = myService;
}
@PostConstruct
public void startWork() {
System.out.println("firstManager start work");
myService.doWork();
}
}
@Component
public static class SecondManager {
private final List<MyService> myServices;
@Autowired // inject MyService all implementations
public SecondManager(List<MyService> myServices) {
this.myServices = myServices;
}
@PostConstruct
public void startWork() {
System.out.println("secondManager start work");
myServices.forEach(MyService::doWork);
}
}
}
Pour la deuxième partie de votre question, regardez ces réponses utiles premier / second
Vous pouvez également le faire fonctionner en lui donnant le nom de l'implémentation.
Par exemple:
@Autowired
MyService firstService;
@Autowired
MyService secondService;
Comme mentionné dans les commentaires, en utilisant le @Qualifier
annotation, vous pouvez distinguer différentes implémentations comme décrit dans docs .
Pour les tests, vous pouvez également faire de même. Par exemple:
@RunWith(SpringRunner.class)
@SpringBootTest
public class MyClassTests {
@Autowired
private MyClass testClass;
@MockBean
@Qualifier("default")
private MyImplementation defaultImpl;
@Test
public void givenMultipleImpl_whenAutowiring_thenReturnDefaultImpl() {
// your test here....
}
}