Skip to content
thesarfo

Recipe

Spring Fundamentals: Wiring & Dependency Injection

Bootstrapping an application context from a config class, and disambiguating between multiple beans of the same type with @Qualifier.

views 0

To bootstrap a plain Spring app (no Boot), create a main package with a Main/App class — that’s where the application context gets created, from an AnnotationConfigApplicationContext pointed at a @Configuration class.

App.java
package dev.thesarfo;
import dev.thesarfo.beans.Owner;
import dev.thesarfo.config.ProjectConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App {
public static void main(String[] args) {
try (AnnotationConfigApplicationContext c = new AnnotationConfigApplicationContext(ProjectConfig.class)) {
Owner o = c.getBean(Owner.class);
System.out.println(o);
}
}
}

Disambiguating multiple beans of the same type

Say we have a Cat bean and an Owner that depends on one:

Cat.java
package dev.thesarfo.beans;
public class Cat {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Cat{name='" + name + "'}";
}
}

If the config defines two Cat beans, Spring has no way to know which one to inject — you need @Qualifier on both the bean definitions and the injection point, naming which one you want:

ProjectConfig.java
package dev.thesarfo.config;
import dev.thesarfo.beans.Cat;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = "dev.thesarfo.beans")
public class ProjectConfig {
@Bean
@Qualifier("cat1") // the name this bean will be stored under in the context
public Cat cat1() {
Cat c = new Cat();
c.setName("Tom");
return c;
}
@Bean
@Qualifier("cat2")
// @Primary // alternative: mark one bean as the default used when no qualifier is given
public Cat cat2() {
Cat c = new Cat();
c.setName("Leo");
return c;
}
}
Owner.java
package dev.thesarfo.beans;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component
public class Owner {
@Qualifier("cat2") // tell the context which Cat bean to use
private Cat cat;
public Cat getCat() {
return cat;
}
public void setCat(Cat cat) {
this.cat = cat;
}
@Override
public String toString() {
return "Owner{cat=" + cat + "}";
}
}

Owner resolves to the cat2 bean (“Leo”) specifically. The alternative to @Qualifier at every injection point is @Primary on one of the candidate bean definitions, marking it as the default whenever no explicit qualifier is given.