Skip to content

Instantly share code, notes, and snippets.

@samhendley
Forked from aleung/ApplicationContextDumper.java
Last active August 29, 2015 14:05
Show Gist options
  • Save samhendley/8535cf15f97efe611f26 to your computer and use it in GitHub Desktop.
Save samhendley/8535cf15f97efe611f26 to your computer and use it in GitHub Desktop.
Slightly improved version that ignores beans that can be considered "root" objects (prototypes, SmartLifecycle,BeanFactoryPostProcessor,ApplicationContextAware)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"
default-lazy-init="false" default-autowire="byName">
<!-- Enable @Autowired -->
<context:annotation-config/>
<!-- Load all beans with @Repository -->
<context:component-scan base-package="leoliang.springtest"/>
<bean id="aNormalBean" class="leoliang.springtest.NormalBean">
<property name="anotherBean" ref="anotherBean"/>
</bean>
<bean class="leoliang.springtest.ApplicationContextDumper" />
</beans>
package leoliang.springtest;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.SmartLifecycle;
import org.springframework.context.support.AbstractRefreshableApplicationContext;
import java.util.HashMap;
import java.util.Map;
public class ApplicationContextDumper implements ApplicationContextAware {
private Map<String, ReferencedData> beanReferenceCounter = new HashMap<String, ReferencedData>();
private StringBuilder outputMessage;
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
outputMessage = new StringBuilder();
beanReferenceCounter.clear();
outputMessage.append("--- ApplicationContextDumper begin ---\n");
dumpApplicationContext(context);
dumpBeansWithoutReference();
outputMessage.append("--- ApplicationContextDumper end ---\n");
System.out.print(outputMessage);
}
private void dumpBeansWithoutReference() {
outputMessage.append("Beans without reference:\n");
for (String beanName : beanReferenceCounter.keySet()) {
ReferencedData ref = beanReferenceCounter.get(beanName);
if (ref.count == 0) {
if (ref.isRootObject) {
continue;
}
outputMessage.append(" ").append(beanName).append('\n');
}
}
}
private ReferencedData initBeanReferenceIfNotExist(String beanName) {
ReferencedData ref = beanReferenceCounter.get(beanName);
if (ref == null) {
ref = new ReferencedData(0);
beanReferenceCounter.put(beanName, ref);
}
return ref;
}
private void increaseBeanReference(String beanName) {
ReferencedData ref = beanReferenceCounter.get(beanName);
if (ref == null) {
ref = new ReferencedData(0);
beanReferenceCounter.put(beanName, ref);
}
ref.count++;
}
private void dumpApplicationContext(ApplicationContext context) {
// Read context id isn't available. https://jira.springsource.org/browse/SPR-8816
String appContextInfo = String.format("ApplicationContext %s : %s", context.getId(), context.getClass()
.getName());
ApplicationContext parent = context.getParent();
if (parent != null) {
appContextInfo += String.format(" -> %s", parent.getId());
}
outputMessage.append(appContextInfo).append('\n');
ConfigurableListableBeanFactory factory = ((AbstractRefreshableApplicationContext)context).getBeanFactory();
for (String beanName : factory.getBeanDefinitionNames()) {
BeanDefinition beanDefinition = factory.getBeanDefinition(beanName);
if (beanDefinition.isAbstract()) {
continue;
}
ReferencedData ref = initBeanReferenceIfNotExist(beanName);
Object bean = factory.getBean(beanName);
if(beanDefinition.isPrototype()
|| bean instanceof SmartLifecycle
|| bean instanceof BeanFactoryPostProcessor
|| bean instanceof ApplicationContextAware){
ref.isRootObject = true;
}
outputMessage.append(String.format(" %s : %s\n", beanName, bean.getClass().getName()));
for (String dependency : factory.getDependenciesForBean(beanName)) {
outputMessage.append(String.format(" -> %s\n", dependency));
increaseBeanReference(dependency);
}
}
if (parent != null) {
outputMessage.append("Parent:\n");
dumpApplicationContext(parent);
}
}
private static class ReferencedData {
int count = 0;
boolean isRootObject = false;
private ReferencedData(int count) {
this.count = count;
}
}
}
<beans>
<bean id="parentBeanFactory" class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg>
<list>
<value>classpath:**/parentContext.xml</value>
</list>
</constructor-arg>
</bean>
<bean id="myBeanFactory" class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg>
<list>
<value>classpath:**/applicationContext.xml</value>
</list>
</constructor-arg>
<constructor-arg>
<ref bean="parentBeanFactory" />
</constructor-arg>
</bean>
</beans>
public static void main(String[] args) {
String[] paths = { "classpath:**/beanRefContext.xml" };
new ClassPathXmlApplicationContext(paths);
}
--- ApplicationContextDumper begin ---
ApplicationContext org.springframework.context.support.ClassPathXmlApplicationContext@e1d5ea : org.springframework.context.support.ClassPathXmlApplicationContext -> parentBeanFactory
org.springframework.context.annotation.internalConfigurationAnnotationProcessor : org.springframework.context.annotation.ConfigurationClassPostProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor : org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor : org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor : org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
repositoryBean : leoliang.springtest.RepositoryBean
-> aNormalBean
aNormalBean : leoliang.springtest.NormalBean
-> anotherBean
leoliang.springtest.ApplicationContextDumper#0 : leoliang.springtest.ApplicationContextDumper
Parent:
ApplicationContext parentBeanFactory : org.springframework.context.support.ClassPathXmlApplicationContext
anotherBean : leoliang.springtest.AnotherBean
Beans without reference:
repositoryBean
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
leoliang.springtest.ApplicationContextDumper#0
--- ApplicationContextDumper end ---
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="abstractBean" abstract="true" />
<bean id="anotherBean" class="leoliang.springtest.AnotherBean" parent="abstractBean" />
</beans>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment