Forked from aleung/ApplicationContextDumper.java
Last active
August 29, 2015 14:05
-
-
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)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static void main(String[] args) { | |
String[] paths = { "classpath:**/beanRefContext.xml" }; | |
new ClassPathXmlApplicationContext(paths); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- 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 --- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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