Primary and Secondary Beans

Primary is a qualifier that indicates that a bean is the primary bean that should be selected in the case of multiple possible interface implementations.

Consider the following example:

  1. public interface ColorPicker {
  2. String color();
  3. }
  1. interface ColorPicker {
  2. String color()
  3. }
  1. interface ColorPicker {
  2. fun color(): String
  3. }

Given a common interface called ColorPicker that is implemented by multiple classes.

The Primary Bean

  1. import io.micronaut.context.annotation.Primary;
  2. import javax.inject.Singleton;
  3. @Primary
  4. @Singleton
  5. class Green implements ColorPicker {
  6. @Override
  7. public String color() {
  8. return "green";
  9. }
  10. }

The Primary Bean

  1. import io.micronaut.context.annotation.Primary
  2. import javax.inject.Singleton
  3. @Primary
  4. @Singleton
  5. class Green implements ColorPicker {
  6. @Override
  7. String color() {
  8. return "green"
  9. }
  10. }

The Primary Bean

  1. import io.micronaut.context.annotation.Primary
  2. import javax.inject.Singleton
  3. @Primary
  4. @Singleton
  5. class Green: ColorPicker {
  6. override fun color(): String {
  7. return "green"
  8. }
  9. }

The Green bean is a ColorPicker, but is annotated with @Primary.

Another Bean of the Same Type

  1. import javax.inject.Singleton;
  2. @Singleton
  3. public class Blue implements ColorPicker {
  4. @Override
  5. public String color() {
  6. return "blue";
  7. }
  8. }

Another Bean of the Same Type

  1. import javax.inject.Singleton
  2. @Singleton
  3. class Blue implements ColorPicker {
  4. @Override
  5. String color() {
  6. return "blue"
  7. }
  8. }

Another Bean of the Same Type

  1. import javax.inject.Singleton
  2. @Singleton
  3. class Blue: ColorPicker {
  4. override fun color(): String {
  5. return "blue"
  6. }
  7. }

The Blue bean is also a ColorPicker and hence you have two possible candidates when injecting the ColorPicker interface. Since Green is the primary it will always be favoured.

  1. @Controller("/testPrimary")
  2. public class TestController {
  3. protected final ColorPicker colorPicker;
  4. public TestController(ColorPicker colorPicker) { (1)
  5. this.colorPicker = colorPicker;
  6. }
  7. @Get
  8. public String index() {
  9. return colorPicker.color();
  10. }
  11. }
  1. @Controller("/test")
  2. class TestController {
  3. protected final ColorPicker colorPicker
  4. TestController(ColorPicker colorPicker) { (1)
  5. this.colorPicker = colorPicker
  6. }
  7. @Get
  8. String index() {
  9. colorPicker.color()
  10. }
  11. }
  1. @Controller("/test")
  2. class TestController(val colorPicker: ColorPicker) { (1)
  3. @Get
  4. fun index(): String {
  5. return colorPicker.color()
  6. }
  7. }
1Although there are two ColorPicker beans, Green gets injected due to the @Primary annotation.

If multiple possible candidates are present and no @Primary is defined then a NonUniqueBeanException will be thrown.

In addition to @Primary, there is also a Secondary annotation which causes the opposite effect and allows de-prioritizing a bean.