Quantcast
Channel: Recent Questions - Stack Overflow
Viewing all articles
Browse latest Browse all 11631

List of Beans and registering beans programmatically via GenericApplicationContext

$
0
0

We have some service interfaces such as:

public interface MyAdapterService {    void doSomething();}

And consumers, which work on all registered instances of this service:

@Service@RequiredArgsConstructorpublic class MyGenericService {    private final List<MyAdapterService> adapterServices;    public void doSomething() {        adapterServices.forEach(MyAdapterService::doSomething);    }}

Depending on how MyAdapterService is registered, they get injected into MyGenericService or not (not always consistantly depending on the MyGenericServicevariant as well, see below).

Class-level annotations such as @Service work fine:

@Service@AllArgsConstructorpublic class MyClassLevelAnnotatedAdapterService implements MyAdapterService{    private final MyDependency myDependency;    @Override    public void doSomething() {        // do something    }}

Method-level generated beans in configurations seem to work just fine, too:

@Configurationpublic class MyConfig {    @Bean    public MyOtherXAdapterService myOtherXAdapterService(MyDependency myDependency) {        return new MyOtherXAdapterService(myDependency);    }}

But programmatically registered beans via GenericApplicationContext don't make it always into the injected List of MyAdapterService:

@Configurationpublic class MyConfig {    public MyConfig(MyDependency myDependency, MyConfigurationProperties properties, GenericApplicationContext applicationContext) {        applicationContext.registerBean("myOtherYAdapterService", MyOtherYAdapterService.class, () -> new MyOtherYAdapterService(myDependency, properties));        MyOtherYAdapterService myOtherYAdapterService = applicationContext.getBean("myOtherYAdapterService", MyOtherYAdapterService.class);        applicationContext.registerBean("myWrapperAdapterService", MyWrapperAdapterService.class, () -> new MyWrapperAdapterService(myOtherYAdapterService));    }    @Bean    public MyOtherXAdapterService myOtherXAdapterService(MyDependency myDependency) {        return new MyOtherXAdapterService(myDependency);    }}

Here: the beans get registered in the constructor of a class annotated with @Configuration.

My findings so far:

  • The MyOtherYAdapterService instance can be resolved directly in the line after its registration (getBean())
  • if the configuration does not also define a @Bean-method, the programmatically registered beans don't make it into the list -> Why?
  • if the configuration does also define a @Bean-method, the programmatically registered beans make it into the list sometimes (depending on the consumer) -> Why?

Questions in general:

  • Why does Spring not wait for all @Configuration-classes to be instantiated before resolving lists of beans? The configuration has a dependency on GenericApplicationContext, so it could be aware that some registration might follow. Is there a way to give Spring a hint to wait for the configuration of the GenericApplicationContext?
  • Why does adding a @Bean-method sometimes make a difference? Is this because of some static analyzing?

The referenced implementations/ code snippets:

@AllArgsConstructorpublic class MyOtherXAdapterService implements MyAdapterService{    private final MyDependency myDependency;    @Override    public void doSomething() {        // do something    }}

and

@AllArgsConstructorpublic class MyOtherYAdapterService implements MyAdapterService{    private final MyDependency myDependency;    private final MyConfigurationProperties properties;    @Override    public void doSomething() {    }}

and

@AllArgsConstructorpublic class MyWrapperAdapterService implements MyAdapterService{    private final MyAdapterService wrappedAdapterService;    @Override    public void doSomething() {        wrappedAdapterService.doSomething();    }}

with

@Servicepublic class MyDependency {    public void doSomethingElse() {        // do something else    }}

and

@Component@Getter@Setter@ConfigurationProperties("my.config")public class MyConfigurationProperties {    private String foo;    private String bar;}

Viewing all articles
Browse latest Browse all 11631

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>