I have below annotation.
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Import(MyBeanInitializer.class)
public @interface MyAnnotation {
String clientType() default "" ;
}
And I have a Bean initialiser component as below
@Configuration
public class MyBeanInitializer {
@Bean() // trigger this when annoattion's value == "A"
public CommonBean firstBean() {
return new BeanA;
}
@Bean() // trigger this when annoattion's value == "B"
public CommonBean firstBean() {
return new BeanB;
}
}
My Commoin interface for BeanA and BeanB
public interface CommonBean {
void doSomething();
}
And my Two Implementations are
@Component()
public class BeanA implements CommonBean {
@Overrid
public void doSomething (){
// implementation here
}
}
@Component()
public class BeanB implements CommonBean {
@Overrid
public void doSomething (){
// implementation here
}
}
I need to use above as an library for another Spring Boot project. In that project I annotate Application.java
with @MyAnnotation(clientType="web")
and then I inject BeanA or BeanB to a class inside that project by using constructor Injection.
What is the mechanism to initialise beans by looking at the values passed through the annotation?
Don't use an annotation value for this.
Annotation values are hard-coded at compile time and cannot be dynamically changed. Plus, it would look and feel incredibly awkward in the face of @Conditional
, which already exists and ties into the ability to get dynamic properties.
What you want to do is use either a combination of @Conditional
which allows you to define what you want to do given a specific environment variable, or use the @ConditionalOnProperty
annotation found in Spring Boot to simply provide the ability to wire in a bean based on the presence of a specific value in a specific property.
Here's how that'd look. Let's assume that you have properties called common.basicImpl
and common.advancedImpl
.
@Component
@ConditionalOnProperty(prefix = "common", value = "basicImpl")
public class BeanA implements CommonBean {
@Override
public void doSomething (){
// implementation here
}
}
@Component
@ConditionalOnProperty(prefix = "common", value = "advancedImpl")
public class BeanB implements CommonBean {
@Override
public void doSomething (){
// implementation here
}
}
Note that this alone wouldn't resolve a circumstance in which both properties were present, and you can't do multiple @ConditionalOnProperty
statements. Adding @ConditionalOnMissingBean
to be sure you don't accidentally wire up both of them at the same time would help you out there.