techmagister
techmagister

Reputation: 1358

How use an annotation's value to initialize a bean

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?

Upvotes: 1

Views: 1077

Answers (1)

Makoto
Makoto

Reputation: 106400

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.

Upvotes: 2

Related Questions