@Override
    public void preInstantiateSingletons() throws BeansException {

        if (this.logger.isInfoEnabled()) {
            this.logger.info("Pre-instantiating singletons in " + this);
        }

        Map< String , BeanInitializer > initializers = new HashMap< String , BeanInitializer >();
        for (String beanName : getBeanDefinitionNames()) {
            if (requiresPreInstantiation(beanName)) {
                addBeanAndDependencies(initializers, beanName, false);
            }
        }

        // AOP advisors appear to have circular dependencies amongst themselves; process them first, serially, so that
        // we don't stall the executor below.
        for (BeanInitializer bi : initializers.values()) {
            if (bi.isAdvisor()) {
                bi.run();
                bi.setStatus(Status.FINISHED);
            }
        }

        // Initialize "normal" beans in parallel; this does not include AOP advisors (above) or beans with dynamic
        // dependencies (below).
        InitializingExecutor executor = new InitializingExecutor(initializers.values());
        executor.run();
        while (!executor.isShutdown()) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                this.logger.warn(e.getMessage(), e);
            }
        }

        // Beans with dynamic dependencies (i.e. they determine their dependencies at runtime via introspection of the
        // other beans in the application context) run last, serially.
        for (BeanInitializer bi : initializers.values()) {
            if (bi.isDynamic()) {
                bi.run();
                bi.setStatus(Status.FINISHED);
            }
        }
    }