Dhana
Dhana

Reputation: 563

Autowiring based on method argument

I have various protocols that my system is using. I mark an interface and provide appropriate implementations. For example SSHprotocol and HttpProtocol both implements Protocol. There may be multiple which I add in the future. Now I have a class as follows:-

class Test {
  @Autowired
  private Protocol protocol;

  public void getProtocol(String name) {
    return protocol;
  }
}

The getProtocol should return a Protocol object based on the Protocol name. In short I want Spring to Autowire the specific bean based on name parameter. Does spring support this? I can have multiple @Autowired with corresponding Qualifiers. But that may make me to write 10-15 variables with corresponding Autowiring annotations. But that is too much of code making it difficult to manage. Factory may be an alternative but how will that solve my problem?

Upvotes: 2

Views: 2550

Answers (2)

Dariusz
Dariusz

Reputation: 22271

You're misunderstanding the @Autowired concept. The wiring, assigning the object, is done once, just after the creation of the object.

edit: dunni's answer is definitely better, unless maybe you want to create a whitelist of protocols

You could @Autowired all protocols and case them:

class Test {
  @Autowired
  private Protocol httpProtocol;

  @Autowired
  private Protocol sshProtocol;

  public void getProtocol(String name) {
    switch(name.toLowerCase()) {
      case "ssh": return sshProtocol;
      case "http": return httpProtocol;
    }
    throw new YourException("unknown protocol "+name);
  }
}

You would have to, of course, have all the Protocol implementation registered as beans with appropriate names. You could do it like that:

@Configuration
class ProtocolConfiguration {

    @Bean
    public Protocol httpProtocol() {
        return new HttpProtocol();
    }

    @Bean
    public Protocol sshProtocol() {
        return new SSHProtocol();
    }
}

Upvotes: 1

dunni
dunni

Reputation: 44545

You can autowire a field of a map type, like that:

@Autowired
private Map<String, Protocol> protocols;

Spring will then populate the map with the bean name as key and the bean instance as value. So in your getProtocol method you could just do

public void getProtocol(String name) {
    return protocols.get(name);
}

You can adjust the bean name of your beans by specifying the value on the component annotation:

@Component("http")
public class HttpProtocol ...

Upvotes: 6

Related Questions