Reputation: 29166
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
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
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