Skip to content

Instantly share code, notes, and snippets.

@gdpotter
Last active November 28, 2018 16:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gdpotter/55e68308ac191308c294a2cc42e596b2 to your computer and use it in GitHub Desktop.
Save gdpotter/55e68308ac191308c294a2cc42e596b2 to your computer and use it in GitHub Desktop.
Spring Circular Dependency Analysis
public class DepGraph {
private final Map<String, Set<String>> nodes;
private DepGraph(Map<String, Set<String>> nodes) {
this.nodes = nodes;
}
public Set<String> calculateCycles() {
Set<String> visited = new HashSet<>();
return nodes.keySet().stream()
.map(node -> calculateCycles(node, visited, Collections.emptyList()))
.flatMap(Set::stream)
.collect(Collectors.toSet());
}
private Set<String> calculateCycles(String node, Set<String> visited, List<String> path) {
List<String> newPath = new LinkedList<>(path);
newPath.add(node);
if (path.contains(node)) {
List<String> cycle = newPath.subList(path.indexOf(node), path.size());
return Collections.singleton(String.join("->", cycle));
}
if (visited.contains(node)) {
return Collections.emptySet();
}
visited.add(node);
Set<String> deps = nodes.getOrDefault(node, Collections.emptySet());
return deps.stream()
.map(dep -> calculateCycles(dep, visited, newPath))
.flatMap(Set::stream)
.collect(Collectors.toSet());
}
public static DepGraph buildDependencyGraph(GenericApplicationContext applicationContext) {
ConfigurableListableBeanFactory factory = applicationContext.getBeanFactory();
Map<String, Set<String>> beanDeps = Arrays.stream(factory.getBeanDefinitionNames())
.filter(beanName -> !factory.getBeanDefinition(beanName).isAbstract())
.collect(Collectors.toMap(
Function.identity(),
beanName -> new HashSet<>(Arrays.asList(factory.getDependenciesForBean(beanName)))
));
return new DepGraph(beanDeps);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment