Reputation: 258
I'd like to create a bean based on "which instance of which class the field belongs to (or even, just to which class this field belongs to). Something like:
@Configuration
@ComponentScan
public class MyConfiguration {
@Bean
SomeClass getTheRightInstance(SomeContext someContext) {
if(someContext.getinjectedFieldHostInstance.getId() == 7) {
return new SpecificSomeClassImplForId7();
} else {
return new SomeClass();
}
}
Bean is to be injected into following field
:
public class A {
private int final id;
@Inject private SomeClass field;
int getId();
public A() {
id = SerialIdGenerator.getNextID();
}
}
Select bean injected into A
's field
based on A
instance's id
public staitc void main(String[] args) {
A a1 = new A(); // has id '1', gets field injected with SimpleClass
A a2 = new A(); // has id '2', gets field injected with SimpleClass
...
A a7 = new A(); // gets field injected with SpecificSomeClassImplForId7
...
A last= new A(); // has id!=7, gets field injected with SimpleClass
}
The general idea is to have the decision as to which implementation to inject to which field in which class be defined in code.
Can I inject different bean instances to the same field of different instances of the same class? How can you configure it through code?
Upvotes: 2
Views: 500
Reputation: 1986
The bean you define is a Singleton, so its created at Context-Initialization before the app know that anyone might autowire the value. You must create the Bean as Prototype
to request the instance on autowire only.
This is still not possible to get infos about the autowire-target. You can use *Aware
-interfaces to get
But neither the target
of the autowire nor the class
of the target.
Notice that: if the autowire-field has been marked as @Lazy
and the Bean's scope is Prototype
you can elaborate the exact time the bean autowires using the bean's @PostConstruct
.
Upvotes: 1
Reputation: 3547
I'm not sure why you want to do that but it seems like a bad idea.
Classes should never configure their behaviour around their caller, it leads to code that is tightly coupled and not very portable.
Instead, you should find out what makes those 2 fields different and refactor them to use 2 different interfaces (which may even have a common super interface in case of shared functionality). Then you can easily provide 2 different implementations for those interfaces. In your case you could also write a class that handles the specific case for id == 7 and the other cases (maybe via delegation) and use another way of configuring the instance either after or while injecting it into A.
I'm not aware of any possibility to do what you want directly.
Edit: After discussing a bit further in the comments and understanding more what you want to accomplish I think having one factory to create A instances would be best:
@Service
class AFactory {
@Autowired
private SpecificSomeClassImplForId7 specificSomeClassImplForId7;
@Autowired
private SomeClass someClass;
public A makeA() {
if(isSpecialA()) {
return new A(specificSomeClassImplForId7);
} else {
return new A(someClass);
}
}
Then you can use this factory in other Spring Beans in your Application to make As.
Upvotes: 1