How to pass constructor parameter while using spring auto wiring?
Spring doesn't work in this way.
Your two beans are too coupled, both in terms of execution and instantiation : as the first one is created, it created during its construction, the second one and it passes to it a generated value at runtime in argument constructor.
Even by playing with dependency injection order (@DependsOn
, @Order
or with two @Configuration
which one depends on the other) it would not solve your problem because of the runtime generated value that is not a dependency.
As a workaround, providing a method to value once creationTime
in the IMessage
interface may be acceptable.
SayHelloService
could look like :
package com.example.demo.services;
import org.springframework.stereotype.Service;
@Service
public class SayHelloService implements IMessage {
String id;
public SayHelloService(String id) {
super();
this.id = id;
}
@Override
public void setId(String id){
// you can add this check to enforce the immutability of id
if (this.id != null){//exception handling}
this.id = id;
}
@Override
public String message(String name) {
return "Hello Dear User - " + name + ". Greeter Id: " + id ;
}
}
And you could change MasterService
in this way :
private IMessage sayHelloServiceAutoWired;
@Autowired
MasterService( @Qualifier("sayHelloService")
IMessage sayHelloServiceAutoWired) {
System.out.println("ms... default constructor");
creationTime = Long.toString(System.currentTimeMillis());
this.sayHelloServiceAutoWired = sayHelloServiceAutoWired;
this.sayHelloServiceAutoWired.setId(creationTime);
}
PS : The autowiring constructor is not mandatory but it is cleaner that having no API to set dependencies of the class. You may also use a setter.
samshers
Updated on June 04, 2022Comments
-
samshers almost 2 years
Our Project is using spring DI/IoC, so i am using autowiring to inject beans. The program needs to pass parameters to an object during it's instantiation. And the parameters are know at run time (not at compile time).
How to achive this while using autowiring. Sample code is as below.
Interface - IMessage
package com.example.demo.services; public interface IMessage { String message(String name); }
Implementations -
SayHelloServicepackage com.example.demo.services; import org.springframework.stereotype.Service; @Service public class SayHelloService implements IMessage { String id; public SayHelloService(String id) { super(); this.id = id; } @Override public String message(String name) { return "Hello Dear User - " + name + ". Greeter Id: " + id ; } }
MasterService
package com.example.demo.services; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; @Service public class MasterService implements IMessage { String creationTime; MasterService() { System.out.println("ms... default constructor"); creationTime = Long.toString(System.currentTimeMillis()); } //classic java way of creating service IMessage sayHelloServiceClassicWay = new SayHelloService(creationTime); //how to achieve above using spring auto wiring. Below code does not exactly do same. @Autowired @Qualifier("sayHelloService") IMessage sayHelloServiceAutoWired; @Override public String message(String name) { return name.toString(); } }
Now in the above program (in MasterService) how to replace
IMessage sayHelloServiceClassicWay = new SayHelloService(creationTime);
with spring equivalent code.
-
samshers over 6 yearscan you please add some code to demo. And will it be runtime. Further my project wan't to avoid xml config. But any way plz share what you want to.
-
samshers over 6 yearsthx for reply. The code snippet
return new B2(1);
value1
is still compile time, i need to pass it at run time. -
Evgeniy Dorofeev over 6 yearsit's not necessary be compile time, you can take that value from a property. But if you say you need to inject a bean (B2) at runtime - you can do it programmatically, Spring is no help, Spring initialization is done during context construction
-
samshers over 6 yearsgr8 answer again. I still see that autowiring on constructor is the way to go. Else autowiring on setter could be other choice.
-
davidxxx over 6 years@samshers Thank you. I tried to improve it a little bit. Reasons of the problem was not clear enough . Setter is also possible but it provides more "rights" to the client class. If it is not a problem, it is valid.