Spring Boot dynamically provide String Beans based on custom annotation from external library

391 Views Asked by At

Background: Let's say I'm in the process of migrating code from old code to Spring Boot 2 applications. The old code had its own IoC mechanism and I'd like to reuse old libraries in new Spring app without modifying the libraries codebase.

Libraries code used field-injections only. It used annotation similar to @Value for injecting some properties, let's say @InjectString. Also every field also had @Inject annotation on top. So all libraries that I'd like to use look more or less like this:

package com.mylibrary;

public class LibraryA {

    @Inject
    @InjectString("db.properties.poolEnabled")
    private String poolEnabled;
...

Assumption:

  • all properties like db.properties.poolEnabled are already present in System.getProperties().
  • the LibraryA class is already under Spring IoC control, it's just missing the required field bean:
No qualifying bean of type 'java.lang.String' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@javax.inject.Inject(), @com.mylibrary.InjectString(name="db.properties.poolEnabled")}

Question: How can I reuse old code and let Spring know what values to put dynamically into the fields with @Inject based on @InjectString name (which can be retrieved from System.getProperty?

I was thinking about 3 potential solutions:

  1. during beans construction, let Spring know that when it's looking for a Bean of type String and it the field has @InjectString annotation, it can get a value from System.getProperty() as the bean value.

  2. during class scan, take all fields with @InjectString and somehow append there a @Value annotations and maybe Spring will know what to insert there

  3. scan for all fields annotated with @InjectString, create String named beans for all of them and append @Resource(name="...") to every fields bean declaration

Which idea sounds the best and which Spring classes will help with implementation?

So far I'd probably prefer solution 1), as it sounds like a single Spring class override. In solution 2) and 3) I'm missing the Spring classes I can override during IoC building to provide extra beans definitions dynamically - do you know what can I use?

Thanks for any hints!

1

There are 1 best solutions below

0
On

Looking at @Value javadoc we will see hint, that processing is done in AutowiredAnnotationBeanPostProcessor and binding is done in AutowireCandidateResolver.

So, I would try with registering additional BeanPostProcessor that will have you @InjectString set as autowiredAnnotationTypes. Then register QualifierAnnotationAutowireCandidateResolver with this annotation.