3.8 Conditional Beans
At times you may want a bean to load conditionally based on various potential factors including the classpath, the configuration, the presence of other beans etc.
The Requires annotation provides the ability to define one or many conditions on a bean.
Consider the following example:
Using @Requires
@Singleton
@Requires(beans = DataSource.class)
@Requires(property = "datasource.url")
public class JdbcBookService implements BookService {
DataSource dataSource;
public JdbcBookService(DataSource dataSource) {
this.dataSource = dataSource;
}
Using @Requires
@Singleton
@Requires(beans = DataSource.class)
@Requires(property = "datasource.url")
class JdbcBookService implements BookService {
DataSource dataSource
Using @Requires
@Singleton
@Requirements(Requires(beans = [DataSource::class]), Requires(property = "datasource.url"))
class JdbcBookService(internal var dataSource: DataSource) : BookService {
The above bean defines two requirements. The first indicates that a DataSource
bean must be present for the bean to load. The second requirement ensures that the datasource.url
property is set before loading the JdbcBookService
bean.
Kotlin currently does not support repeatable annotations. Use the @Requirements annotation when multiple requires are needed. For example, @Requirements(Requires(…), Requires(…)) . See https://youtrack.jetbrains.com/issue/KT-12794 to track this feature. |
If you have multiple requirements that you find you may need to repeat on multiple beans then you can define a meta-annotation with the requirements:
Using a @Requires meta-annotation
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PACKAGE, ElementType.TYPE})
@Requires(beans = DataSource.class)
@Requires(property = "datasource.url")
public @interface RequiresJdbc {
}
Using a @Requires meta-annotation
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target([ElementType.PACKAGE, ElementType.TYPE])
@Requires(beans = DataSource.class)
@Requires(property = "datasource.url")
@interface RequiresJdbc {
}
Using a @Requires meta-annotation
@Documented
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.CLASS, AnnotationTarget.FILE)
@Requirements(Requires(beans = [DataSource::class]), Requires(property = "datasource.url"))
annotation class RequiresJdbc
In the above example an annotation called RequiresJdbc
is defined that can then be used on the JdbcBookService
instead:
Using a meta-annotation
@RequiresJdbc
public class JdbcBookService implements BookService {
...
}
If you have multiple beans that need to fulfill a given requirement before loading then you may want to consider a bean configuration group, as explained in the next section.