Is it possible to construct an object manually and let some other arguments be injected by Spring?
e.g.
class A
#Autowired
private SomeDao dao;
A(String x, String y) {}
Your example is using field injection, not constructor injection.
The best way is generally to use JavaConfig. Your #Bean methods can take parameters (which Spring will autowire), which you can combine with your other options when you call new.
Maybe org.springframework.web.context.support.SpringBeanAutowiringSupport class it's what you are looking for, try to invoke:
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
You can use autowireBean from the AutowireCapableBeanFactory. Given your applicationContext, you call getAutowireCapableBeanFactory() and then autowire your instance:
applicationContext.getAutowireCapableBeanFactory().autowireBean( new A("x", "y" ) );
Related
i have this specific question regarding spring IOC . I want to achieve runtime polymorphism using spring .
I am able to achieve the same using if else , however i would like a know a proper spring-way of doing it .
Requirement :
I have interface MyInterface .
ImplA & ImplB implements MyInterface .
I have a service which sends "A" or "B" . Based on the request-param i want to inject ImplA or ImplB in my controller .
Please suggest what will be the best way to implement the same in spring using dependency injection
If you use spring annotation base configuration try it:
#Bean(name = "aImpl")
public MyInterface a() {
return new AImpl();
}
#Bean(name = "bImpl")
public MyInterface b() {
return new BImpl();
}
To get the properly instance of interface clarify bean name with #Qualifier
#Autowired
#Qualifier("a")
MyInterface aImpl;
#Autowired
#Qualifier("b")
MyInterface bImpl;
There are many ways to achieve this. Couple of ideas from my point of view:
Use Factory pattern to return the bean you want based on the param value.
Put both the beans in map and using param values as key. When you need the bean get it from the map.
Let me know if you need more information.
You can use applicationContext.getBean("beanName") inside your controller method. Here is an example program. You can get the right impl this way based on your condition.
Java Spring question:
I have a interface MyInterface with one method
void exec (String str);
I have many implementation of MyInterface, say Oneimpl, anotherimpl yetanotherimpl...and so on and can keep adding new implementations.
how do I obtain an instance of a specific implementation using just the name of the implementing class passed as a STRING value , say "someRandomImpl"
The code should be dynamic and can provide a instance of new implementations without code change.
implements ApplicationContextAware
it will autowired ApplicationContext object
use the object like
context.getBean(beanName)
then you get the bean
I am interested to inject a bean reference, which is resolved based on another property on the same bean:
#Autowired
#Qualifier("#{'prefix' + actualQualifier}")
private OtherBean otherBean
private String actualQualifier;
This would ensure that the relationship between "actualQualifier" and "otherBean" is correct.
There is a number of beans configured of the type OtherBean.
I can make sure that "actualQualifier" has a value set before autowiring/injection begins.
I am unable to find any way to reference another property value (in the JavaBean sense) on the same bean that is currently being autowired.
AFAIK, this will not work. SpEL has no access to variables of the enclosing class. And anyway, it looks like #Qualifier does not process SpEL expressions.
I did some tests and never found how to use a SpEL expression as a #Qualifier value. This page from Spring forums (and the error messages from Spring) let me think that in fact #Qualifier only takes a String and does not try to evaluate a SpEL expression.
My conclusion is that way will lead you in a dead end.
As suggested in this other answer, I think you'd better use a selector bean and set otherBean in an init method :
#Bean(initMethod="init")
class MyBean {
...
#Autowired
private BeanSelector beanSelector;
private OtherBean otherBean
private String actualQualifier;
public void init() {
otherBean = beanSelector(actualQualifier);
}
...
}
and put all intelligence about the choice of otherBean in beanSelector.
If I have:
#Autowired private ApplicationContext ctx;
I can get beans and resources by using one of the the getBean methods. However, I can't figure out how to get property values.
Obviously, I can create a new bean which has an #Value property like:
private #Value("${someProp}") String somePropValue;
What method do I call on the ApplicationContext object to get that value without autowiring a bean?
I usually use the #Value, but there is a situation where the SPeL expression needs to be dynamic, so I can't just use an annotation.
In the case where SPeL expression needs to be dynamic, get the property value manually:
somePropValue = ctx.getEnvironment().getProperty("someProp");
If you are stuck on Spring pre 3.1, you can use
somePropValue = ctx.getBeanFactory().resolveEmbeddedValue("${someProp}");
Assuming that the ${someProp} property comes from a PropertyPlaceHolderConfigurer, that makes things difficult. The PropertyPlaceholderConfigurer is a BeanFactoryPostProcessor and as such only available at container startup time. So the properties are not available to a bean at runtime.
A solution would be to create some sort of a value holder bean that you initialize with the property / properties you need.
#Component
public class PropertyHolder{
#Value("${props.foo}") private String foo;
#Value("${props.bar}") private String bar;
// + getter methods
}
Now inject this PropertyHolder wherever you need the properties and access the properties through the getter methods
My spring bean have a constructor with an unique mandatory argument, and I managed to initialize it with the xml configuration :
<bean name="interfaceParameters#ota" class="com.company.core.DefaultInterfaceParameters">
<constructor-arg>
<value>OTA</value>
</constructor-arg>
</bean>
Then I use this bean like this and it works well.
#Resource(name = "interfaceParameters#ota")
private InterfaceParameters interfaceParameters;
But I would like to specify the contructor arg value with the annocations, something like
#Resource(name = "interfaceParameters#ota")
#contructorArg("ota") // I know it doesn't exists!
private InterfaceParameters interfaceParameters;
Is this possible ?
Thanks in advance
First, you have to specify the constructor arg in your bean definition, and not in your injection points. Then, you can utilize spring's #Value annotation (spring 3.0)
#Component
public class DefaultInterfaceParameters {
#Inject
public DefaultInterfaceParameters(#Value("${some.property}") String value) {
// assign to a field.
}
}
This is also encouraged as Spring advises constructor injection over field injection.
As far as I see the problem, this might not suit you, since you appear to define multiple beans of the same class, named differently. For that you cannot use annotations, you have to define these in XML.
However I do not think it is such a good idea to have these different beans. You'd better use only the string values. But I cannot give more information, because I dont know your exact classes.
As Bozho said, instead of constructor arg you could set the property...#PostConstruct will only get called after all the properties are set...so, you will still have your string available ...