I want to choose a property file based which is decided by calling a method in another bean. Example
#Component
#PropertySource("classpath:app-${app.getName('value')}.properties")
class AppConfig{}
class App is a bean in my spring boot program.
Is there a way to do it?
TLDR: I want to provide a value in placeholder by calling a method from other bean.
Related
My question is: Why does this piece of code correctly set the constructor parameter property port:
private final RedisServer redisServer;
public RedisTestConfiguration(#Value("${cache.port}") final int port) {
this.redisServer = new RedisServer(port);
}
As of my understanding, #Value("${cache.port}") is resolved by a BeanPostProcessor called AutowiredAnnotationBeanPostProcessor. Spring bean lifecycle works in a way that the constructor method is called before any BeanPostProcess, see picture below. Note The constructor is called before BeanPostProcessor.postProcessBeforeInitialization().
How come this is still working?
Regards,
Bart
This behavior is supported by PropertySourcesPlaceholderConfigurer
Ref: https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-factory-placeholderconfigurer
PropertySourcesPlaceholderConfigurer is a BeanFactoryPostProcessor. It collects #Value fields and updates bean definition in spring container. PropertySourcesPlaceholderConfigurer should be created in the container before any bean is initialized.
Bean metadata is described here in the documentation:
https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-factory-metadata
So, the flow is the following:
1. Bean definition readers collect beans declarations in xml files or from java classes. Example, XmlBeanDefinitionReader.
Ref: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/xml/XmlBeanDefinitionReader.html
Bean Factory Post Processors update bean definitions. Example, PropertySourcesPlaceholderConfigurer.
Spring container looks at the bean definition and creates beans(calls constructor) according to bean definition values.
Ref: https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-factory-class
So, the problem is that
As of my understanding, #Value("${cache.port}") is resolved by a BeanPostProcessor is not correct. #Value is managed by BeanFactoryPostProcessor, not BeanPostProcessor
Actually, documentation states:
A default lenient embedded value resolver is provided by Spring. It will try to resolve the property value and if it cannot be resolved, the property name (for example ${catalog.name}) will be injected as the value. If you want to maintain strict control over nonexistent values, you should declare a PropertySourcesPlaceholderConfigurer bean, as the following example shows:...
Spring has some kind of default property resolver, that is another BeanFactoryPostProcessor. But it is possible to override it with PropertySourcesPlaceholderConfigurer
Is there any annotation/trick in Spring that marks a #Configuration #Bean as injectable only on strictly qualified #Autowireds?
I'd like my bean to be qualified in a way that only those that specifically call for its #Qualifer can inject it. It's indeed a mechanism for controlling where is it going to be able to be autowired, with no ambiguity nor arbitrary decisions depending on available beans in the context.
So my bean would never be autowired as a side-effect out-of-my control without me actively marking the injecting as expecting it
You can control bean creation with #Conditional annotation.
Also if you need real control of using bean you can create some annotation like #ConroledByQualifer and use this annotation instead of standard spring component annotation , or extension for one (like service , repository .... ) .
So spring can't process it for autowired as one don't know how to handling it.
You need add custom BeanPostProcessor that will work with #ConroledByQualifer - create it and inject. So your custom bean will be processed only by BeanPostProcessor for #ConroledByQualifer and not custom spring BeanPostProcessors.
I have a class A with a date field annotated with #Value to take as default value the current date.
When I create a bean in an XML file, this field appears to be initialized with the current date, as expected.
When I create a new object with new A() in main of a test class, the field is null.
My question is how does #Value work. In the documentation, it said it gives a default value to a field, but does it work only for beans? How is it processed?
When creating the bean using the XML file, Spring creates the bean and applies the injection of configured fields, via XML configuration or decorated by annotations e.g. #Autowired, #Value, etc...
When creating the bean using new YourClass, then you're manually creating an instance of the class, thus not being handled by Spring.
If you want Spring to handle new beans created on demand i.e. using new keyword, you can refer to Spring injecting or autowiring datasource bean to class, point 3 and the explanation at the bottom using #Configurable.
I have a situation and im trying to figure out why it is so. The scenario is I have a class A that implements an operation exposed by a webservice. For each request for the operation a new instance of A is created. The entire thing is manged by Spring internally and I am not sure how exactly the Class A in instantiated by the webservice.
Now i have a class variable whose value i want to inject during runtime through
#Value("${someValue}")
String someVariable
someValue is defined a system property. But each of the beans created has someVariable as NULL.
I tried the same thing in another class annotated with #Configuration in the same package and it is resolving the variable fine.
So, Im thinking if the ability to inject through #Value depends on the way a bean is created like #Component, #Configuration-#Bean, XML definiti
Not really. Actually You can inject value with #Value in both the component scan bean and xml definition bean. But pay attention to this, It depends on which xml file that you put the Placeholder in, it just valids in the per-container. For example, you put it in applicationContext, then the bean create in xxx-servlet.xml can not inject value with #Value.
I'm using annotation configuration and I currently cannot use request scope for my controller, but I need one of the bean that controller uses to be a prototype. So I figured the best way would be getting prototypes for a singleton controller via method injection.
But then I realized that Spring's method injection needs an abstract class so that I couldn't use my annotation configuration ...
Could please anybody tell me how to do that ? It seems to me that it is very common scenario, but currently it can be realized only via "request scope" of controller.
Or I'd have to make my controller ApplicationContextAware and get the bean from context. But can annotation-config #Controller be ApplicationContextAware ?
You can simply #Inject ApplicationContext ctx, but you need your other bean to be defined in the child context (dispatcher-servlet.xml) (you need that anyway). And then you can look it up.
There is no way to define lookup-method injection with annotations currently. There is an open issue about that. So for this particular controller you can use xml configuration to define the lookup-method.