spring-projects/spring-framework · error · IllegalStateException

Lifecycle annotation requires a no-arg method: {}

Error message

Lifecycle annotation requires a no-arg method: {}

What it means

A method carrying a lifecycle annotation (@PostConstruct/@PreDestroy or a custom one configured on InitDestroyAnnotationBeanPostProcessor) declares one or more parameters. Spring requires lifecycle methods to be no-arg, verified in the LifecycleMethod constructor before the method is registered. This is a configuration/programming error detected at bean-class introspection time.

Source

Thrown at spring-beans/src/main/java/org/springframework/beans/factory/annotation/InitDestroyAnnotationBeanPostProcessor.java:436

			Collection<LifecycleMethod> destroyMethodsToUse =
					(checkedDestroyMethods != null ? checkedDestroyMethods : this.destroyMethods);
			return !destroyMethodsToUse.isEmpty();
		}
	}


	/**
	 * Class representing an annotated init or destroy method.
	 */
	private static class LifecycleMethod {

		private final Method method;

		private final String identifier;

		public LifecycleMethod(Method method, Class<?> beanClass) {
			if (method.getParameterCount() != 0) {
				throw new IllegalStateException("Lifecycle annotation requires a no-arg method: " + method);
			}
			this.method = method;
			this.identifier = (isPrivateOrNotVisible(method, beanClass) ?
					ClassUtils.getQualifiedMethodName(method) : method.getName());
		}

		public Method getMethod() {
			return this.method;
		}

		public String getIdentifier() {
			return this.identifier;
		}

		public void invoke(Object target) throws Throwable {
			ReflectionUtils.makeAccessible(this.method);
			this.method.invoke(target);
		}

View on GitHub (pinned to e8729d0438)

Solutions

  1. Remove all parameters from the @PostConstruct/@PreDestroy method so its signature is void-compatible with zero args.
  2. If you need a collaborator, inject it as a field or constructor argument and reference it from the no-arg lifecycle method.
  3. If you intended a different method, move the annotation to the correct no-arg method.

Example fix

// before
@PostConstruct
public void init(DataSource ds) { /* wrong */ }
// after
@Autowired
private DataSource ds;

@PostConstruct
public void init() { ds.getConnection(); }
Defensive patterns

Strategy: validation

Validate before calling

ReflectionUtils.doWithMethods(beanType, m -> {
  if (m.isAnnotationPresent(PostConstruct.class) || m.isAnnotationPresent(PreDestroy.class)) {
    if (m.getParameterCount() != 0) throw new IllegalStateException(
      m + " must be no-arg to qualify as a lifecycle method");
  }
});

Type guard

boolean isNoArgLifecycle(Method m) {
  return (m.isAnnotationPresent(PostConstruct.class)
       || m.isAnnotationPresent(PreDestroy.class))
       && m.getParameterCount() == 0;
}

Prevention

When it happens

Trigger: Annotating a method that takes arguments with @PostConstruct or @PreDestroy (or the custom init/destroy annotation type set via setInitAnnotationType/setDestroyAnnotationType). The check fails immediately when the bean class is scanned for lifecycle methods.

Common situations: Developer adds a parameter to a @PostConstruct method (e.g. to inject a collaborator positionally), copies a pattern from another framework that allows args, or uses a custom lifecycle annotation on an existing business method that happens to take parameters.

Related errors


AI-assisted analysis of spring-projects/spring-framework@e8729d0438 (2026-08-04). Data as JSON: /data/errors/17ae9f633177a6a9.json. Report an issue: GitHub.