Crystal
Crystal

Reputation: 29518

Spring DI with dynamic constructor arguments

Most of my classes wired up look something like:

@Component
public class MyClassImpl implements MyClass {

   private MyService service;

   @Autowired
   public MyClass(MyService service) {
      this.service = service;
   }
}

So that makes sense to me, but if I want to do something like this:

@Component
public class MyClassImpl implements MyClass {

   private MyService service;
   private String id;       // this is what I need

   @Autowired
   public MyClass(MyService service, String id) {
      this.service = service;
      this.id = id;
   }
}

But the problem is String id is not known until runtime. Is there any way to do this? From what I can tell, Spring checks all the dependencies by default at runtime so if I try the second example, it complains about the constructor arguments.

I've seen some examples where you can use a factory to create the actual value later down the line. Or I can create getters and setters in order to set the id when I need it, but that would also mean I'd need to add those getters and setters to the interface MyClass as well. Is there a cleaner way to do this?

Upvotes: 1

Views: 1531

Answers (2)

Vitalii Vitrenko
Vitalii Vitrenko

Reputation: 10425

You can create a @Bean method for id with logic needed to calculate it.

@Configuration
public class Config {
    @Bean
    public String idForService() {
        return calculateId();
    }
}

And then your service constructor will be look like this

   @Autowired
   public MyClass(MyService service, @Qualifier("idForService") String id) {
      this.service = service;
      this.id = id;
   }

But as others have already mentioned it looks like a bad practice so you'd better consider to redesign your service class.

Upvotes: 1

Mateusz Chrzaszcz
Mateusz Chrzaszcz

Reputation: 1280

I am afraid what you are trying to do is not in the spirit of what Spring was created for. Please do have a look at: Runtime dependency injection with Spring

Having said that, there might be a workaround to your problem. If you have some class that calculates that ID for you, just inject that class in a constructor and bind the result of its calculation to the field id in your class.

Upvotes: 0

Related Questions