Search code examples
javaspringspring-bootstartup

Call static init method that needs a bean on Spring startup, without exposing another bean


Hello I have the task to call the some initialization code that needs a bean (config) without exposing another bean that would do the initialization. So far I failed to accomplish that without an initializer bean.

use case: The CarFactory has a static ìnit method that has a PartProvider as parameter and should be called after the a PartProviderbean is available. CarFactory and SeatProvider are from a dependencies and cannot be changed.

import javax.inject.Inject;

public abstract class CarFactory {

    private static PartProvider partProvider;

    private CarFactory() {
    }

    @Inject
    public static void init(final PartProvider partProvider) {
        PartProvider.partProvider = partProvider;
    }
}
public class SeatProvider implements PartProvider {

    Config config;

    @Inject
    public SeatProvider(@NonNull Config config) {
        this.config = config;
   }

}

My current code that exposes the initializer bean

initalizer bean


public class FactoryInitializer implements InitializingBean {

    private PartProvider partProvider

    @Inject
    public FactoryInitializer(PartProvider partProvider) {
        this.partProvider = partProvider;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        CarFactory.init(provider);
    }
}

configuration


@Configuration
public class AppConfiguration {

    @Bean
    public FactoryInitializer factoryInitializer(final Config config) {
        return new FactoryInitializer(new SeatProvider(config));
    }
}

This an ugly but working 'hack'. That produces an Object bean that is null.

@Bean
public Object notificationInit(final Config config) {
    CarFactory.init(new SeatProvider(config));
    return null;
}

What I really need to do is call the following code, at a place where the config is available.

CarFactory.init(new SeatProvider(config));

Solution

  • This solved my problem as @michalk suggested. The configuration is a bean itself that I need anyways. It gets the config injected and runs the initialization code in its @PostConstruct init() method.

    So the config is available as a bean and there is no need for an initializer class.

    @Configuration
    public class AppConfiguration {
    
        @Inject
        private Config config;
    
        @PostConstruct
        public void init() throws Exception {
            CarFactory.init(new SeatProvider(config));
        }
    }