spring-projects/spring-framework · error · IllegalStateException

CustomAutowireConfigurer needs to operate on a…

Error message

CustomAutowireConfigurer needs to operate on a DefaultListableBeanFactory

What it means

Thrown by CustomAutowireConfigurer.postProcessBeanFactory() when the BeanFactory it receives is not an instance of DefaultListableBeanFactory. CustomAutowireConfigurer must install custom qualifier types on the AutowireCandidateResolver, which is only available on DefaultListableBeanFactory. Any other BeanFactory type is incompatible.

Solutions

  1. Use a context backed by DefaultListableBeanFactory (GenericApplicationContext, AnnotationConfigApplicationContext, ClassPathXmlApplicationContext all use it by default).
  2. If using a custom BeanFactory, extend DefaultListableBeanFactory rather than implementing BeanFactory from scratch.
  3. Remove CustomAutowireConfigurer if custom qualifier types are not actually needed — @Qualifier works without it.
Defensive patterns

Strategy: validation

Validate before calling

// Verify the BeanFactory type before deploying CustomAutowireConfigurer
if (!(beanFactory instanceof DefaultListableBeanFactory)) {
    throw new IllegalStateException(
        "CustomAutowireConfigurer requires DefaultListableBeanFactory, got: "
        + beanFactory.getClass().getName());
}

Type guard

// Type guard: check before using CustomAutowireConfigurer
if (beanFactory instanceof DefaultListableBeanFactory dlbf) {
    CustomAutowireConfigurer configurer = new CustomAutowireConfigurer();
    configurer.setCustomQualifierTypes(Set.of(MyQualifier.class));
    configurer.postProcessBeanFactory(dlbf);
} else {
    // use standard ApplicationContext instead
}

Prevention

When it happens

Trigger: Registering CustomAutowireConfigurer as a BeanFactoryPostProcessor in a context whose underlying BeanFactory is not a DefaultListableBeanFactory (e.g., a custom BeanFactory implementation or certain test fixtures).

Common situations: Using a custom ApplicationContext with a non-standard BeanFactory. Manually wiring CustomAutowireConfigurer against a SimpleJndiBeanFactory or StaticListableBeanFactory. Test setups with mock/custom BeanFactory implementations.

Related errors


AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09). Data as JSON: /api/errors/cdaf4d8cf3cdda82. Report an issue: GitHub.

Appendix: source

Thrown at spring-beans/src/main/java/org/springframework/beans/factory/annotation/CustomAutowireConfigurer.java:94

	 * when autowiring beans. Each element of the provided set may
	 * be either a Class instance or a String representation of the
	 * fully-qualified class name of the custom annotation.
	 * <p>Note that any annotation that is itself annotated with Spring's
	 * {@link org.springframework.beans.factory.annotation.Qualifier}
	 * does not require explicit registration.
	 * @param customQualifierTypes the custom types to register
	 */
	public void setCustomQualifierTypes(Set<?> customQualifierTypes) {
		this.customQualifierTypes = customQualifierTypes;
	}


	@Override
	@SuppressWarnings("unchecked")
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		if (this.customQualifierTypes != null) {
			if (!(beanFactory instanceof DefaultListableBeanFactory dlbf)) {
				throw new IllegalStateException(
						"CustomAutowireConfigurer needs to operate on a DefaultListableBeanFactory");
			}
			if (!(dlbf.getAutowireCandidateResolver() instanceof QualifierAnnotationAutowireCandidateResolver)) {
				dlbf.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
			}
			QualifierAnnotationAutowireCandidateResolver resolver =
					(QualifierAnnotationAutowireCandidateResolver) dlbf.getAutowireCandidateResolver();
			for (Object value : this.customQualifierTypes) {
				Class<? extends Annotation> customType = null;
				if (value instanceof Class) {
					customType = (Class<? extends Annotation>) value;
				}
				else if (value instanceof String className) {
					customType = (Class<? extends Annotation>) ClassUtils.resolveClassName(className, this.beanClassLoader);
				}
				else {
					throw new IllegalArgumentException(
							"Invalid value [" + value + "] for custom qualifier type: needs to be Class or String.");

View on GitHub (pinned to 69bf83ad71)