Home > Software design >  Spring Boot conditional loading bean
Spring Boot conditional loading bean

Time:11-07

im running a spring boot project and I'm trying to load some beans conditionaly. I have the following configuration file:

application:
    components:
        componentA:
            - ex1
              ex2
              ex3
        componentB:
            - ex1
              ex2
              ex3
        componentC:
            - ex1
              ex2
              ex3
    use: componentA

and the following configuration classes

@Configuration
@ConfigurationProperties(prefix = "application.components")
@Primary
@Getter
@Setter
@NoArgsConstrutor
public class MainConfig
{
    private List<ComponentAConfig> componentA = new ArrayList<ComponentAConfig>();
    private List<ComponentBConfig> componentB = new ArrayList<ComponentBConfig>();
    private List<ComponentCConfig> componentC = new ArrayList<ComponentCConfig>();

}
@Getter
@Setter
@NoArgsConstrutor
public abstract class ComponentConfig
{
    private String ex1;
    private String ex2;
    private String ex3;
}
@Configuration
@ConditionalOnProperty(prefix = "application", name = "use", havingValue = "componentA")
public class ComponentAConfig extends ComponentConfig
{
    
}
@Configuration
@ConditionalOnProperty(prefix = "application", name = "use", havingValue = "componentB")
public class ComponentBConfig extends ComponentConfig
{
    
}
@Configuration
@ConditionalOnProperty(prefix = "application", name = "use", havingValue = "componentC")
public class ComponentCConfig extends ComponentConfig
{
    
}

Even though I have the @ConditionalOnProperty defined on each configuration class its still loads all of them. How can I load only componentA's list and ignore the other 2? Thank you

CodePudding user response:

I guess, I would do that like this. (Edited based on later comment)

The config part class:

@Data
@NoArgsConstructor
public class ComponentConfigPart {
    private String ex1;
    private String ex2;
    private String ex3;
}

The base class for the bean

@Data
public abstract class ComponentConfig {
    private List<ComponentConfigPart> parts = new ArrayList<>();

    @PostConstruct
    public void init() {
        System.out.println("Created instance of "   this.getClass().getSimpleName());
        System.out.println("Created "   this);
    }
}

The ComponentA class

@Component
@ConfigurationProperties(prefix = "application.components.a")
@ConditionalOnProperty(prefix = "application", name = "use", havingValue = "componentA")
@ToString(callSuper = true)
public class ComponentAConfig extends ComponentConfig {
    
}

The ComponentB class:

@Component
@ConfigurationProperties(prefix = "application.components.b")
@ConditionalOnProperty(prefix = "application", name = "use", havingValue = "componentB")
@ToString(callSuper = true)
public class ComponentBConfig extends ComponentConfig {

}

and the MainConfig, which wants to get the "selected" component:

@Configuration
public class MainConfig {

    @Autowired
    private ComponentConfig config;

    @PostConstruct
    public void init() {
        System.out.println("MainConfig has autowired class of "   config.getClass().getSimpleName());
    }
}

Now, the properties are like this:

application:
  components:
    a:
      parts:
        - ex1: a
          ex2: aa
          ex3: aaa
        - ex1: a2
          ex2: aa2
          ex3: aaa2
    b:
      parts:
        - ex1: b
          ex2: bb
          ex3: bbb
        - ex1: b2
          ex2: bb2
          ex3: bbb2
  use: componentA

And results in console logs:

Created instance of ComponentAConfig
Created ComponentAConfig(super=ComponentConfig(parts=[ComponentConfigPart(ex1=a, ex2=aa, ex3=aaa), ComponentConfigPart(ex1=a2, ex2=aa2, ex3=aaa2)]))
MainConfig has autowired class of ComponentAConfig

Similarly, if the properties are like:

application:
  components:
    a:
      parts:
        - ex1: a
          ex2: aa
          ex3: aaa
        - ex1: a2
          ex2: aa2
          ex3: aaa2
    b:
      parts:
        - ex1: b
          ex2: bb
          ex3: bbb
        - ex1: b2
          ex2: bb2
          ex3: bbb2
  use: componentB

The result is:

Created instance of ComponentBConfig
Created ComponentBConfig(super=ComponentConfig(parts=[ComponentConfigPart(ex1=b, ex2=bb, ex3=bbb), ComponentConfigPart(ex1=b2, ex2=bb2, ex3=bbb2)]))
MainConfig has autowired class of ComponentBConfig

CodePudding user response:

That is the behavior that Im looking for, but each component is meant to be a list like this :

application:
  components:
    componentA:
        - ex1
          ex2
          ex3
        - ex1
          ex2
          ex3
    componentB:
        - ex1
          ex2
          ex3
        - ex1
          ex2
          ex3
    componentC:
        - ex1
          ex2
          ex3
        - ex1
          ex2
          ex3
use: componentA

Thats why I had the MainConfig class with each list.

  • Related