@Test
  public void listenersInApplicationContextWithNestedChild() {
    StaticApplicationContext context = new StaticApplicationContext();
    RootBeanDefinition nestedChild = new RootBeanDefinition(StaticApplicationContext.class);
    nestedChild.getPropertyValues().add("parent", context);
    nestedChild.setInitMethodName("refresh");
    context.registerBeanDefinition("nestedChild", nestedChild);
    RootBeanDefinition listener1Def = new RootBeanDefinition(MyOrderedListener1.class);
    listener1Def.setDependsOn(new String[] {"nestedChild"});
    context.registerBeanDefinition("listener1", listener1Def);
    context.refresh();

    MyOrderedListener1 listener1 = context.getBean("listener1", MyOrderedListener1.class);
    MyEvent event1 = new MyEvent(context);
    context.publishEvent(event1);
    assertTrue(listener1.seenEvents.contains(event1));

    SimpleApplicationEventMulticaster multicaster =
        context.getBean(
            AbstractApplicationContext.APPLICATION_EVENT_MULTICASTER_BEAN_NAME,
            SimpleApplicationEventMulticaster.class);
    assertFalse(multicaster.getApplicationListeners().isEmpty());

    context.close();
    assertTrue(multicaster.getApplicationListeners().isEmpty());
  }
  /**
   * Read a particular {@link ConfigurationClassMethod}, registering bean definitions with the
   * BeanDefinitionRegistry based on its contents.
   */
  private void loadBeanDefinitionsForBeanMethod(ConfigurationClassMethod beanMethod) {
    ConfigurationClass configClass = beanMethod.getConfigurationClass();
    MethodMetadata metadata = beanMethod.getMetadata();

    RootBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass);
    beanDef.setResource(configClass.getResource());
    beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
    beanDef.setFactoryBeanName(configClass.getBeanName());
    beanDef.setUniqueFactoryMethodName(metadata.getMethodName());
    beanDef.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
    beanDef.setAttribute(
        RequiredAnnotationBeanPostProcessor.SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);

    // consider name and any aliases
    Map<String, Object> beanAttributes = metadata.getAnnotationAttributes(Bean.class.getName());
    List<String> names =
        new ArrayList<String>(Arrays.asList((String[]) beanAttributes.get("name")));
    String beanName =
        (names.size() > 0 ? names.remove(0) : beanMethod.getMetadata().getMethodName());
    for (String alias : names) {
      this.registry.registerAlias(beanName, alias);
    }

    // has this already been overridden (e.g. via XML)?
    if (this.registry.containsBeanDefinition(beanName)) {
      BeanDefinition existingBeanDef = registry.getBeanDefinition(beanName);
      // is the existing bean definition one that was created from a configuration class?
      if (!(existingBeanDef instanceof ConfigurationClassBeanDefinition)) {
        // no -> then it's an external override, probably XML
        // overriding is legal, return immediately
        if (logger.isDebugEnabled()) {
          logger.debug(
              String.format(
                  "Skipping loading bean definition for %s: a definition for bean "
                      + "'%s' already exists. This is likely due to an override in XML.",
                  beanMethod, beanName));
        }
        return;
      }
    }

    if (metadata.isAnnotated(Primary.class.getName())) {
      beanDef.setPrimary(true);
    }

    // is this bean to be instantiated lazily?
    if (metadata.isAnnotated(Lazy.class.getName())) {
      beanDef.setLazyInit(
          (Boolean) metadata.getAnnotationAttributes(Lazy.class.getName()).get("value"));
    } else if (configClass.getMetadata().isAnnotated(Lazy.class.getName())) {
      beanDef.setLazyInit(
          (Boolean)
              configClass.getMetadata().getAnnotationAttributes(Lazy.class.getName()).get("value"));
    }

    if (metadata.isAnnotated(DependsOn.class.getName())) {
      String[] dependsOn =
          (String[]) metadata.getAnnotationAttributes(DependsOn.class.getName()).get("value");
      if (dependsOn.length > 0) {
        beanDef.setDependsOn(dependsOn);
      }
    }

    Autowire autowire = (Autowire) beanAttributes.get("autowire");
    if (autowire.isAutowire()) {
      beanDef.setAutowireMode(autowire.value());
    }

    String initMethodName = (String) beanAttributes.get("initMethod");
    if (StringUtils.hasText(initMethodName)) {
      beanDef.setInitMethodName(initMethodName);
    }

    String destroyMethodName = (String) beanAttributes.get("destroyMethod");
    if (StringUtils.hasText(destroyMethodName)) {
      beanDef.setDestroyMethodName(destroyMethodName);
    }

    // consider scoping
    ScopedProxyMode proxyMode = ScopedProxyMode.NO;
    Map<String, Object> scopeAttributes = metadata.getAnnotationAttributes(Scope.class.getName());
    if (scopeAttributes != null) {
      beanDef.setScope((String) scopeAttributes.get("value"));
      proxyMode = (ScopedProxyMode) scopeAttributes.get("proxyMode");
      if (proxyMode == ScopedProxyMode.DEFAULT) {
        proxyMode = ScopedProxyMode.NO;
      }
    }

    // replace the original bean definition with the target one, if necessary
    BeanDefinition beanDefToRegister = beanDef;
    if (proxyMode != ScopedProxyMode.NO) {
      BeanDefinitionHolder proxyDef =
          ScopedProxyCreator.createScopedProxy(
              new BeanDefinitionHolder(beanDef, beanName),
              this.registry,
              proxyMode == ScopedProxyMode.TARGET_CLASS);
      beanDefToRegister = proxyDef.getBeanDefinition();
    }

    if (logger.isDebugEnabled()) {
      logger.debug(
          String.format(
              "Registering bean definition for @Bean method %s.%s()",
              configClass.getMetadata().getClassName(), beanName));
    }

    registry.registerBeanDefinition(beanName, beanDefToRegister);
  }