Order of bean initialization in Spring - java

I have the following beans in my Spring config file:
<bean id="myList" class="java.util.ArrayList">
<constructor-arg>
<list>
<ref bean="elem1"/>
<ref bean="elem2"/>
<ref bean="elem3"/>
<ref bean="elem4"/>
</list>
</constructor-arg>
</bean>
<bean id="elem4" class="myClass">
<property name="title" value="random4"/>
</bean>
<bean id="elem1" class="myClass">
<property name="title" value="random1"/>
</bean>
<bean id="elem3" class="myClass">
<property name="title" value="random3"/>
</bean>
<bean id="elem2" class="myClass">
<property name="title" value="random2"/>
</bean>
I have noticed that in my application the elements in myList are in the following order: elem4, elem1, elem3, elem2. I was expecting that the elements in my list will be in the order I set when I declared the ref beans ( elem1, elem2, elem3, elem4).
Is there an order in which Spring initializes beans?
Is there a way I can specify an order for the elements in my list?

The spring does respect the order you gave in the list. The elements in the list would exactly be the [elem1,elem2,elem3,elem4] as you specified. Otherwise, you are doing something wrong, can you show the code which prints you the different order?
The order of bean initialization however may be different and depends on bean dependencies, so, for example if you have two beans
<bean id="holder" class="my.HolderBean" lazy-init="false">
<property name="inner" ref="inner"/>
</bean>
<bean id="inner" class="my.InnerBean" lazy-init="false"/>
Then regardless of the xml definition order, the InnerBean will be initialized first, then during HolderBean initialization it will be injected into HolderBean.

Related

Spring. How to add same property to multiple beans?

Consider I have something like this in beans.xml:
<bean id="emails" class="org.some.package.SomeClass">
<property name="emailList">
<list>
<value>pechorin#hero.org</value>
<value>raskolnikov#slums.org</value>
<value>stavrogin#gov.org</value>
<value>porfiry#gov.org</value>
</list>
</property>
</bean>
But I need to add emailList property into multiple beans. How can I do that without writing property to each bean? Can externalize property and inject it into each bean?
I expect something like:
<property name="commonProp">
<list>
<value>pechorin#hero.org</value>
<value>raskolnikov#slums.org</value>
<value>stavrogin#gov.org</value>
<value>porfiry#gov.org</value>
</list>
</property>
<bean id="emailsOne" class="org.some.package.ClassOne">
<property name="emailList" ref="commonProp" />
</bean>
<bean id="emailsTwo" class="org.some.package.ClassTwo">
<property name="emailList" ref="commonProp" />
</bean>
You can do it using: util:list
<util:list id="myList" value-type="java.lang.String">
<value>foo</value>
<value>bar</value>
</util:list>
Then use this myList reference in other beans.

Spring XML Configuration - How to specify property value for a group of objects?

Say I have the following beans defined.
<bean id="testBean1" class="org.springframework.beans.TestBean" scope="prototype">
<property name="hariColor" value="Black"/>
<property name="spouse">
<bean class="org.springframework.beans.TestBean">
<property name="age" value="11"/>
</bean>
</property>
</bean>
<bean id="testBean2" class="org.springframework.beans.TestBean" scope="prototype">
<property name="hariColor" value="Black"/>
<property name="spouse">
<bean class="org.springframework.beans.TestBean">
<property name="age" value="19"/>
</bean>
</property>
</bean>
I have a set of beans with hairColor Black, another set of beans with hairColor Blonde etc.. Is there a way in Spring to group all Black hair color beans together and define the hairColor in only one place rather than specifying for each bean?
Yes you can achieve it via abstract="true" element in Spring's bean as explained below
<bean id="blackHairColor" abstract="true">
<property name="prop1" ref="someBlackBean"/>
<property name="prop2" ref="someOtherBlackBean"/>
</bean>
<bean id="blondeHairColor" abstract="true">
<property name="prop1" ref="someBlondeBean"/>
<property name="prop2" ref="someOtherBlondeBean"/>
</bean>
<bean id="someBean1" class="a.b.c.d" parent="blackHairColor">
<property name="someOtherProp" ref="someRef1"/>
</bean>
<bean id="someBean2" class="a.b.c.d" parent="blondeHairColor">
<property name="someOtherProp" ref="someRef1"/>
</bean>
Here we define two abstract beans with respective properties. Do note that these abstract beans do not have a class attached to them and thus creates a set of common properties which could be re-used in other bean(s).
To inherit the abstract bean simply mention their id in the parent element of bean definition. Also note that the bean class does not need to inherit any class to inherit another bean i.e. class a.b.c.d do not need to inherit any class for the bean inheritance to work.

How to reuse Spring XML fragments

I am working on Spring based application. The XML is simple but contains several almost identical fragments. For example I have 5 different DAO objects, 2 queues etc. Configuration of each DAO looks like:
<bean id="deviceDaoTarget" class="com.mycompany.dao.hibernate.DeviceDAOHibernateImpl"
autowire="byName" />
<bean id="deviceDAO" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>com.mycompany.dao.DeviceDAO</value>
</property>
<property name="interceptorNames">
<list>
<value>hibernateInterceptor</value>
<value>deviceDaoTarget</value>
</list>
</property>
</bean>
I'd be happy to use some kind of import with parameters. For example I'd like to create parametrized configuration of DAO like this:
<bean id="${dao.target}" class="${dao.class}"
autowire="byName" />
<bean id="deviceDAO" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>${dao.interface}</value>
</property>
<property name="interceptorNames">
<list>
<value>hibernateInterceptor</value>
<value>${dao.target}</value>
</list>
</property>
</bean>
and then call it several times with different parameters, e.g.:
<import resource="spring-dao.xml">
<param name="dao.interface">com.mycompany.dao.hibernate.DeviceDAO</param>
<param name="dao.class">com.mycompany.dao.hibernate.DeviceDAOHibernateImpl</param>
<param name="dao.target">deviceDaoTarget</param>
</import>
Is something like this possible?
You can define a <bean id="parentBean" abstract="true" ...>...</bean> with the common configuration and then have <bean id="childBean" parent="parentBean" ...>...</bean> with just specific configuration for that bean.

Spring: Getting FactoryBean object instead of FactoryBean.getObject()

Short question: If I have class that impelemnts FactoryBean interface, how can I get from FactoryBean object itself instead of FactoryBean.getObject()?
Long question: I have to use 3-rd party Spring based library which is hardly use FactoryBean interface. Right now I always must configure 2 beans:
<!-- Case 1-->
<bean id="XYZ" class="FactoryBean1" scope="prototype">
<property name="steps">
<bean class="FactoryBean2">
<property name="itemReader" ref="aName"/>
</bean>
</property>
</bean>
<bean id="aName" class="com.package.ClassName1" scope="prototype">
<property name="objectContext">
<bean class="com.package.ABC"/>
</property>
</bean>
<!-- Case 2-->
<bean id="XYZ2" class="FactoryBean1" scope="prototype">
<property name="steps">
<bean class="FactoryBean2">
<property name="itemReader" ref="aName2"/>
</bean>
</property>
</bean>
<bean id="aName2" class="com.package.ClassName1" scope="prototype">
<property name="objectContext">
<bean class="com.package.QWE"/>
</property>
</bean>
Actyually defintion of a bean with name "XYZ" (compare with "XYZ2") never will be changed, but because of factory nature I must copy the code for each configuration.
Definition of a bean with name "aName" always will be new (i.e. each configuration will have own objectContext value).
I would like to simplify the configuration have a single factory bean (remove "XYZ2" and rid of link to "aName"):
<bean id="XYZ" class="FactoryBean1" scope="prototype">
<property name="steps">
<bean class="FactoryBean2"/>
</property>
</bean>
<bean id="aName" class="com.package.ClassName1" scope="prototype">
<property name="objectContext">
<bean class="com.package.ABC"/>
</property>
</bean>
<bean id="aName2" class="com.package.ClassName1" scope="prototype">
<property name="objectContext">
<bean class="com.package.QWE"/>
</property>
</bean>
Unfortunately, it's not as simple as I expect. I suppose to glue factory (i.e. XYZ bean from the example) with necessary objects (i.e. "aName", "aName2") at runtime.
The approach doesn't work because when I ask Spring for FactoryBean object it returns to me FactoryBean.getObject() which impossible to instanciate at that time because of missing itemReader value.
I hope that SpringSource foresee my case I can somehome "hook" FactoryBean.getObject() call to provide all necessary properties at runtime.
Another complexity that disturb me a bit it's chains of Factories (Factory1 get an object from Factory2 that I have to "hook" at runtime).
Any ideas will be appreciated.
It's the & (ampersand), not the At-symbol, see Spring Framework documentation: Customizing instantiation logic using FactoryBeans
<property name="factoryBean" ref="&theFactoryBean" />
You can get the factory bean itself using the & syntax in the spring config:
<property name="factoryBean" ref="&theFactoryBean" />
as opposed to:
<property name="createdBean" ref="theFactoryBean" />

spring: set property of one bean by reading the property of another bean?

Is it possible to set the property of one bean by reading the property of another bean? For instance, suppose I had:
class A {
void setList(List list);
}
class B {
List getList();
}
I would like Spring to instantiate both classes, and call A's setList method, passing in the result of calling B's getList method. The Spring configuration might look something like:
<bean id="b" class="B"/>
<bean id"a" class="A">
<property name="list" ref="b" ref-property="list"/>
</bean>
Alas, this made-up XML does not work.
Why not just inject B into A? Because I do not want to introduce the extra dependency. A is only dependent List, not on B.
in addition to #Kevin's answer if you are using spring 3.0 it is possible to do this with the new spring expression language
<bean id="a" class="A">
<property name="list"
value="#{b.list}"/>
</bean>
spring 3.0 documentation
There are a couple of ways. Here is one:
<bean id="b" class="B"/>
<bean id="a" class="A">
<property name="list">
<bean class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
<property name="targetObject" ref="b"/>
<property name="propertyPath" value="list"/>
</bean>
</property>
</bean>
Also see the <util:property-path/> element
If you are trying to do the same for a constructor then do this.
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg type="javax.sql.DataSource" value="#{jdbc.dataSource}">
</constructor-arg>
</bean>
Here "jdbc" is as mentioned below that has property "dataSource" with getter and setter and initilized as:
<bean id="jdbc" class="com.la.activator.DataSourceProvider">
<property name="myDataSourcePool" ref="dsPoolService"/>
</bean>

Categories