DEV Community

Query Filter
Query Filter

Posted on

bridge79

package com.yourpackage;

import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.SmartLifecycle;
import java.util.HashSet;
import java.util.Set;

public class SpringVisualizer implements ApplicationContextAware, SmartLifecycle {

    private ConfigurableApplicationContext startContext;
    private boolean isRunning = false;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.startContext = (ConfigurableApplicationContext) applicationContext;
    }

    @Override
    public void start() {
        System.out.println("\n=== STARTING RECURSIVE HIERARCHY SCAN ===");
        try {
            generateMasterGraph();
        } catch (Exception e) {
            System.err.println("Scan interrupted: " + e.getMessage());
            e.printStackTrace();
        }
        this.isRunning = true;
    }

    private void generateMasterGraph() {
        StringBuilder dot = new StringBuilder("digraph MasterBeanMap {\n");
        dot.append("  rankdir=LR; node [shape=box, style=filled, color=\"#E1F5FE\", fontname=\"Courier\"];\n");

        Set<String> processedBeans = new HashSet<>();
        int totalReportedDefinitions = 0;
        ApplicationContext current = this.startContext;

        while (current != null) {
            ConfigurableListableBeanFactory factory = ((ConfigurableApplicationContext) current).getBeanFactory();
            totalReportedDefinitions += factory.getBeanDefinitionCount();

            String[] names = factory.getBeanDefinitionNames();
            for (String name : names) {
                if (processedBeans.add(name)) { // Avoid duplicates if contexts overlap
                    String[] deps = factory.getDependenciesForBean(name);
                    for (String dep : deps) {
                        dot.append(String.format("  \"%s\" -> \"%s\";\n", name, dep));
                    }

                    // Highlight your specific modules
                    if (name.toLowerCase().contains("comet")) dot.append(String.format("  \"%s\" [fillcolor=\"#FFF9C4\"];\n", name));
                    if (name.toLowerCase().contains("cpls")) dot.append(String.format("  \"%s\" [fillcolor=\"#C8E6C9\"];\n", name));
                }
            }
            current = current.getParent();
        }

        dot.append("}\n");

        // --- SYNC CHECK MESSAGE ---
        System.out.println("\n------------------------------------------------");
        System.out.println("GRAPH STATUS: Discovered " + processedBeans.size() + " unique beans.");
        System.out.println("SPRING REPORT: Total defined beans across hierarchy: " + totalReportedDefinitions);

        if (processedBeans.size() < totalReportedDefinitions) {
            System.out.println("NOTE: Some beans are 'Inner' or 'Anonymous' and may not appear as top-level nodes.");
        }
        System.out.println("------------------------------------------------\n");

        System.out.println("----- COPY START FOR EDOTOR.NET -----");
        System.out.println(dot.toString());
        System.out.println("----- COPY END -----\n");
        System.out.flush();
    }

    @Override public int getPhase() { return Integer.MAX_VALUE; }
    @Override public boolean isAutoStartup() { return true; }
    @Override public void stop() { this.isRunning = false; }
    @Override public boolean isRunning() { return this.isRunning; }
    @Override public void stop(Runnable callback) { stop(); callback.run(); }
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)