private Object handleTypeMismatchException(
      String beanName, RootBeanDefinition mbd, Object[] args) {
    // type mismatch probably occured because another class was reloaded
    final Class<?> beanClass = mbd.getBeanClass();
    if (!GroovyObject.class.isAssignableFrom(beanClass)) {
      return null;
    }

    GrailsApplication application = (GrailsApplication) getBean(GrailsApplication.APPLICATION_ID);
    ClassLoader classLoader = application.getClassLoader();
    if (!(classLoader instanceof GrailsClassLoader)) {
      return null;
    }

    GrailsClassLoader gcl = (GrailsClassLoader) classLoader;
    gcl.reloadClass(beanClass.getName());
    Class<?> newBeanClass;
    try {
      newBeanClass = gcl.loadClass(beanClass.getName());
    } catch (ClassNotFoundException e) {
      return null;
    }

    mbd.setBeanClass(newBeanClass);
    if (newBeanClass.equals(beanClass)) {
      return null;
    }

    GrailsPluginManager pluginManager =
        (GrailsPluginManager) getBean(GrailsPluginManager.BEAN_NAME);
    pluginManager.informOfClassChange(newBeanClass);
    return super.doCreateBean(beanName, mbd, args);
  }
  public void preInstantiateSingletons() throws BeansException {
    if (logger.isDebugEnabled()) {
      logger.debug("Pre-instantiating singletons in factory [" + this + "]");
    }

    // The superclass's variable by this name is declared private.
    String[] beanDefinitionNames = getBeanDefinitionNames();
    String beanName = null; // Remember in case of an exception
    try {
      // for (Iterator it = this.beanDefinitionNames.iterator();
      // it.hasNext();) {
      for (int i = 0; i < beanDefinitionNames.length; i++) {
        beanName = beanDefinitionNames[i];
        if (!containsSingleton(beanName) && containsBeanDefinition(beanName)) {
          RootBeanDefinition bd = (RootBeanDefinition) getMergedBeanDefinition(beanName);
          if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            if (bd.hasBeanClass() && FactoryBean.class.isAssignableFrom(bd.getBeanClass())) {
              FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);
              if (factory.isSingleton()) {
                getBean(beanName);
              }
            } else {
              getBean(beanName);
            }
          }
        }
      }
    } catch (BeansException ex) {
      // Destroy already created singletons to avoid dangling resources.
      logger.error(
          "Failed to preinstantiate the singleton named "
              + beanName
              + ". Destroying all Spring beans.",
          ex);
      try {
        destroySingletons();
      } catch (Exception ex2) {
        logger.error(
            "Pre-instantiating singletons failed, and couldn't destroy already created singletons: "
                + ex2,
            ex2);
      }
      throw ex;
    }
  }
  public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {

    // Don't override the class with CGLIB if no overrides.
    if (beanDefinition.getMethodOverrides().isEmpty()) {
      Class clazz = beanDefinition.getBeanClass();
      if (clazz.isInterface()) {
        throw new BeanInstantiationException(clazz, "Specified class is an interface");
      }
      try {
        Constructor constructor = clazz.getDeclaredConstructor((Class[]) null);
        return BeanUtils.instantiateClass(constructor, null);
      } catch (Exception ex) {
        throw new BeanInstantiationException(clazz, "No default constructor found", ex);
      }
    } else {
      // Must generate CGLIB subclass.
      return instantiateWithMethodInjection(beanDefinition, beanName, owner);
    }
  }
  /** Match the given qualifier annotation against the candidate bean definition. */
  protected boolean checkQualifier(
      BeanDefinitionHolder bdHolder, Annotation annotation, TypeConverter typeConverter) {

    Class<? extends Annotation> type = annotation.annotationType();
    RootBeanDefinition bd = (RootBeanDefinition) bdHolder.getBeanDefinition();
    AutowireCandidateQualifier qualifier = bd.getQualifier(type.getName());
    if (qualifier == null) {
      qualifier = bd.getQualifier(ClassUtils.getShortName(type));
    }
    if (qualifier == null) {
      Annotation targetAnnotation = null;
      if (bd.getResolvedFactoryMethod() != null) {
        targetAnnotation = AnnotationUtils.getAnnotation(bd.getResolvedFactoryMethod(), type);
      }
      if (targetAnnotation == null) {
        // look for matching annotation on the target class
        if (this.beanFactory != null) {
          Class<?> beanType = this.beanFactory.getType(bdHolder.getBeanName());
          if (beanType != null) {
            targetAnnotation =
                AnnotationUtils.getAnnotation(ClassUtils.getUserClass(beanType), type);
          }
        }
        if (targetAnnotation == null && bd.hasBeanClass()) {
          targetAnnotation =
              AnnotationUtils.getAnnotation(ClassUtils.getUserClass(bd.getBeanClass()), type);
        }
      }
      if (targetAnnotation != null && targetAnnotation.equals(annotation)) {
        return true;
      }
    }
    Map<String, Object> attributes = AnnotationUtils.getAnnotationAttributes(annotation);
    if (attributes.isEmpty() && qualifier == null) {
      // if no attributes, the qualifier must be present
      return false;
    }
    for (Map.Entry<String, Object> entry : attributes.entrySet()) {
      String attributeName = entry.getKey();
      Object expectedValue = entry.getValue();
      Object actualValue = null;
      // check qualifier first
      if (qualifier != null) {
        actualValue = qualifier.getAttribute(attributeName);
      }
      if (actualValue == null) {
        // fall back on bean definition attribute
        actualValue = bd.getAttribute(attributeName);
      }
      if (actualValue == null
          && attributeName.equals(AutowireCandidateQualifier.VALUE_KEY)
          && expectedValue instanceof String
          && bdHolder.matchesName((String) expectedValue)) {
        // fall back on bean name (or alias) match
        continue;
      }
      if (actualValue == null && qualifier != null) {
        // fall back on default, but only if the qualifier is present
        actualValue = AnnotationUtils.getDefaultValue(annotation, attributeName);
      }
      if (actualValue != null) {
        actualValue = typeConverter.convertIfNecessary(actualValue, expectedValue.getClass());
      }
      if (!expectedValue.equals(actualValue)) {
        return false;
      }
    }
    return true;
  }