I am trying to write a Spring BeanFactoryPostProcessor that can find any bean which defines an init-method. I am having luck finding beans that have names, but not nested nameless beans as in the target bean in following example:
<bean id="aclDao" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager"><ref bean="transactionManager"/></property>
<property name="target">
<bean class="com.vidsys.dao.impl.acl.ACLDaoImpl" init-method="init">
<property name="sessionFactory"><ref local="sessionFactory"/></property>
</bean>
</property>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
When I list the beans in my BeanFactoryPostProcessor I only seem to get the ones with names as in the following code:
public class BeanInitializationFinder implements BeanFactoryPostProcessor, Ordered {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
//String[] beanDefs = BeanFactoryUtils.beanNamesIncludingAncestors(beanFactory);
String[] beanDefs = beanFactory.getBeanDefinitionNames();
for(String defName : beanDefs) {
BeanDefinition def = beanFactory.getBeanDefinition(defName);
if(null == def.getBeanClassName() || !(def instanceof AbstractBeanDefinition))
return;
}
AbstractBeanDefinition abd = (AbstractBeanDefinition) def;
try {
if(abd.getFactoryMethodName() == null && abd.getFactoryBeanName() == null)
Class<?> beanClass = Class.forName(abd.getBeanClassName());
if(InitializingBean.class.isAssignableFrom(beanClass) || null != abd.getInitMethodName()) {
beansWithInits.add(defName);
}
}
}
catch(Exception e) {
throw new BeanIntrospectionException("Failed to instrospect bean defs", e);
}
}
}
}
I would like to get all the bean that have an init-method, including nested beans that are nameless. Can I do that?
You can retrieve nested BeanDefinitions, but not via beanFactory.getBeanDefinition
. The only way to get to nested bean definitions is through the PropertyValues
of the parent BeanDefinition
- you need to walk the graph.
By way of example (and missing any null-checking):
BeanDefinition parentDef = beanFactory.getBeanDefinition(defName);
for (PropertyValue property : parentDef.getPropertyValues().getPropertyValues()) {
Object value = property.getValue();
if (value instanceof BeanDefinitionHolder) {
BeanDefinition nestedDef = ((BeanDefinitionHolder)value).getBeanDefinition();
}
}
Given that graph traversal works well with the Visitor pattern, you can subclass org.springframework.beans.factory.config.BeanDefinitionVisitor
to do this in a more concise fashion.