MD Sayem Ahmed
MD Sayem Ahmed

Reputation: 29166

Spring - differences between @Named and @Component

I am trying to understand the differences between these two annotations and how they affect injection in Spring. Consider the following piece of code -

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ExternalPropertiesHolder {}

When I mark a class with this annotation -

@ExternalPropertiesHolder
public class SomeProperties {}

and then this dependency is injected using @Inject, it works perfectly -

@Service
public class SomeService {
    private SomeProperties someProperties;

    @Inject
    public SomeService(SomeProperties someProperties) {
        this.someProperties = someProperties;
    }
}

However, when I replace @Component with @Named -

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Named           // --> Here!
public @interface ExternalPropertiesHolder {}

Then the injection fails with the usual bean not found exception -

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.hogehoge.SomeProperties] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}

I searched the Spring reference documentation, and all it has to say about the difference is this -

JSR-330 does not provide a composable model, just a way to identify named components.

What does that mean? Does it mean that I cannot use @Named to compose a custom marker like this? Or is there something else?

P.S.: Of course by @Component I am referring to org.springframework.stereotype.Component and by @Named I am referring to javax.inject.Named.

Upvotes: 2

Views: 3995

Answers (2)

Prateek Pande
Prateek Pande

Reputation: 505

Correct, javax.inject.Named and javax.anotations.ManagedBean doesn't provide a composable model. Thus, can't be used with the same intent as org.springframework.stereotype.Component.

But i could see from the documentation, we could use javax.inject.Qualifier in this use-case, as it's meant to be used for defining custom annotations.

Did you gave @Qualifier from javax a try ?

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Qualifier           // --> from javax.inject
public @interface ExternalPropertiesHolder {}

Even the @Named is defined using @Qualifier.

@Qualifier
@Documented
@Retention(RUNTIME)
public @interface Named {

    /** The name. */
    String value() default "";
}

Upvotes: 0

MD Sayem Ahmed
MD Sayem Ahmed

Reputation: 29166

So I got the answer directly from Juergen Hoeller. According to him, this line -

JSR-330 does not provide a composable model, just a way to identify named components.

means that the javax.inject.Named can only be declared directly on a given bean class. The composable annotation story just works with Spring's own annotations, which is exactly what I suspected.

Upvotes: 4

Related Questions