1
votes

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?

1
can you share the code where you want the bean to be injected? And most importantly both bean are of different types. BeanA and BeanB, do you plan to move them to a single Interface? It's not clear what exactly you want to do - iam.Carrot
Annotation's value is A/B where? Nothing is annotated with MyAnnotation in your example. - Sotirios Delimanolis
Also, Spring already has @Conditional for conditional definitions. - Sotirios Delimanolis
@iam.Carrot I have added the use case of this to the end. - techmagister
@DinethSenevirathne Since BeanA and BeanB are two different DataTypes can you please share what exactly are you trying to do? You've shared The How but we want to know The Why. What is it that you're trying to achieve? Maybe give an example of what the condition would be and what what would happen when the condition is true and what would happen if the condition is false. How would you use the two different datatypes? Is there a common interface you've declared that you haven't mentioned? - iam.Carrot

1 Answers

2
votes

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.