Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Spring Autowire With Qualifiers

DZone's Guide to

Spring Autowire With Qualifiers

How to implement the Spring annotation Autowired in a variety of situations with multiple qualifiers.

· Java Zone
Free Resource

What every Java engineer should know about microservices: Reactive Microservices Architecture.  Brought to you in partnership with Lightbend.

Introduction

Autowired is great annotation, which by default inject beans by type to annotated element (constructor, setter or field). But how to use it, when there is more than one bean of requested type.

Autowired With One Bean

Suppose we will work with small interface:

interface IHeaderPrinter {
    String printHeader(String header)
}

When we have only one bean implementing IHeaderPrinter:

@Component
class HtmlHeaderPrinter implements IHeaderPrinter{
    @Override
    String printHeader(String header) {
        return "<h1>$header</h1>"
    }
}

Then everything works great and the test passes.

@Autowired
IHeaderPrinter headerPrinter

@Test
void shouldPrintHtmlHeader() {
    assert headerPrinter.printHeader('myTitle') == '<h1>myTitle</h1>'
}

Two Implementations

But what will happen if we add another implementation of IHeaderPrinter, e. g. MarkdownHeaderPrinter?

@Component
class MarkdownHeaderPrinter implements IHeaderPrinter {
    @Override
    String printHeader(String header) {
        return "# $header"
    }
}

Now out test with fail with exception:

Error creating bean with name 'com.blogspot.przybyszd.spring.autowire.SpringAutowireWithQualifiersApplicationTests': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.blogspot.przybyszd.spring.autowire.IHeaderPrinter com.blogspot.przybyszd.spring.autowire.SpringAutowireWithQualifiersApplicationTests.headerPrinter; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.blogspot.przybyszd.spring.autowire.IHeaderPrinter] is defined: expected single matching bean but found 2: markdownHeaderPrinter,htmlHeaderPrinter

We have to decide which implementation we want to use in our test, so ...

Two Implementations With Qualifier

Each bean is registered with name equal its class. For example HtmlHeaderPrinter is named htmlHeaderPrinter. The name is also its qualifier. We have to tell Autowired, that it should inject htmlHeaderPrinter:

@Autowired
@Qualifier('htmlHeaderPrinter')
IHeaderPrinter headerPrinter

Now our test passes again.

Two Implementations Qualified By Field Name

If field is names like implementing class (for example htmlHeaderPrinter), then this class implementation will be injected:

@Autowired
IHeaderPrinter htmlHeaderPrinter

And test passes:

@Test
void shouldPrintHtmlHeader() {
    assert htmlHeaderPrinter.printHeader('myTitle') == '<h1>myTitle</h1>'
}

Thanks to @marcinjasion.

Two Implementations With Primary

We often have one implementation which we almost always want to inject, so do we still have to put Qualifier with its name wherever we want to use it? No.

We could mark one implementation as Primary and this bean will be wired by default (unless we explicit give another Qualifier to use injection point):

@Component
@Primary
class HtmlHeaderPrinter implements IHeaderPrinter{
    // ...
}
@Autowired
IHeaderPrinter headerPrinter

Summary

Autowired annotation allows us to inject dependencies to beans. It works great without additional configuration, when each bean could be uniquely find by type. When we have more than one bean, that could be injected, we have to use Qualifier or Primary annotation to help it find desired implementation.

Source code is available here.

Microservices for Java, explained. Revitalize your legacy systems (and your career) with Reactive Microservices Architecture, a free O'Reilly book. Brought to you in partnership with Lightbend.

Topics:
autowiring ,spring ,primary ,groovy ,dependecy injection

Published at DZone with permission of Dominik Przybysz. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}