Home > database >  Java Spring - Dynamically inject multiple different interface implementations based on configuration
Java Spring - Dynamically inject multiple different interface implementations based on configuration

Time:10-07

Suppose I have an interface (Note: Object is used for example simplicity, not in practice)

public interface IObjectGenerator {
    public List<Object> getObjectsFromThing(String thing);
}

and multiple implementations of this interface

@Service
public class FromFileObjectGenerator implements IObjectGenerator {
    // File interaction supporting vars and functions

    public List<Object> getObjectsFromThing(String thing){
        // Use file stuff to generate and return list of objects
    }
}

@Service
public class FromDatabaseObjectGenerator implements IObjectGenerator {
    // DB interaction supporting vars and functions
    
    public List<Object> getObjectsFromThing(String thing) {
        // Use DB stuff to generate and return list of objects
    }
}

@Service
public class FromWebObjectGenerator implements IObjectGenerator {
    // Web interaction supporting vars and functions
    
    public List<Object> getObjectsFromThing(String thing) {
        // Use Web stuff to generate and return list of objects
    }
}

Sometimes I only want to leverage the file based generator, sometimes the file and db, or db and web, or all of them, etc.

So, I think I need to be able to set which implementations to inject, from at least one of them, up to all of them (and any that may be created in the future), and any combination in between. This needs to be done in configuration file (like application.properties).

public class GeneratorUser {
    private List<IObjectGenerator> generators;

    @Autowired
    public GeneratorUser(List<IObjectGenerator> generators){
        this.generators = generators;
    }
}

I've seen the possibility of making an overarching management class that instantiates all of the generator, injecting the management class, and have it only return the generators necessary when queried, but I'd prefer to prevent instantiating the unused generators at all if possible. Is there an easy way to go about this?

CodePudding user response:

This is actually quite simple. The term here is "Conditional beans".

@Service
@ConditionalOnProperty(value="a.b.c", havingValue = "true")
public class FromFileObjectGenerator implements IObjectGenerator {
   //
}

This will tell the system to only create the bean if the key "a.b.c" in the application.properties is set to "true". There are a lot more @ConditionalOn... annotations, check https://www.baeldung.com/spring-conditional-annotations.

  • Related