{"id":"17ae9f633177a6a9","repo":"spring-projects/spring-framework","slug":"lifecycle-annotation-requires-a-no-arg-method","errorCode":null,"errorMessage":"Lifecycle annotation requires a no-arg method: {}","messagePattern":"Lifecycle annotation requires a no-arg method: (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"spring-beans/src/main/java/org/springframework/beans/factory/annotation/InitDestroyAnnotationBeanPostProcessor.java","lineNumber":436,"sourceCode":"\t\t\tCollection<LifecycleMethod> destroyMethodsToUse =\n\t\t\t\t\t(checkedDestroyMethods != null ? checkedDestroyMethods : this.destroyMethods);\n\t\t\treturn !destroyMethodsToUse.isEmpty();\n\t\t}\n\t}\n\n\n\t/**\n\t * Class representing an annotated init or destroy method.\n\t */\n\tprivate static class LifecycleMethod {\n\n\t\tprivate final Method method;\n\n\t\tprivate final String identifier;\n\n\t\tpublic LifecycleMethod(Method method, Class<?> beanClass) {\n\t\t\tif (method.getParameterCount() != 0) {\n\t\t\t\tthrow new IllegalStateException(\"Lifecycle annotation requires a no-arg method: \" + method);\n\t\t\t}\n\t\t\tthis.method = method;\n\t\t\tthis.identifier = (isPrivateOrNotVisible(method, beanClass) ?\n\t\t\t\t\tClassUtils.getQualifiedMethodName(method) : method.getName());\n\t\t}\n\n\t\tpublic Method getMethod() {\n\t\t\treturn this.method;\n\t\t}\n\n\t\tpublic String getIdentifier() {\n\t\t\treturn this.identifier;\n\t\t}\n\n\t\tpublic void invoke(Object target) throws Throwable {\n\t\t\tReflectionUtils.makeAccessible(this.method);\n\t\t\tthis.method.invoke(target);\n\t\t}","sourceCodeStart":418,"sourceCodeEnd":454,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/e8729d043887bf0d0baf91e062e909b56eb2b708/spring-beans/src/main/java/org/springframework/beans/factory/annotation/InitDestroyAnnotationBeanPostProcessor.java#L418-L454","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Remove all parameters from the @PostConstruct/@PreDestroy method so its signature is void-compatible with zero args.","If you need a collaborator, inject it as a field or constructor argument and reference it from the no-arg lifecycle method.","If you intended a different method, move the annotation to the correct no-arg method."],"exampleFix":"// before\n@PostConstruct\npublic void init(DataSource ds) { /* wrong */ }\n// after\n@Autowired\nprivate DataSource ds;\n\n@PostConstruct\npublic void init() { ds.getConnection(); }","handlingStrategy":"validation","validationCode":"ReflectionUtils.doWithMethods(beanType, m -> {\n  if (m.isAnnotationPresent(PostConstruct.class) || m.isAnnotationPresent(PreDestroy.class)) {\n    if (m.getParameterCount() != 0) throw new IllegalStateException(\n      m + \" must be no-arg to qualify as a lifecycle method\");\n  }\n});","typeGuard":"boolean isNoArgLifecycle(Method m) {\n  return (m.isAnnotationPresent(PostConstruct.class)\n       || m.isAnnotationPresent(PreDestroy.class))\n       && m.getParameterCount() == 0;\n}","tryCatchPattern":null,"preventionTips":["Treat @PostConstruct/@PreDestroy as void, zero-arg methods by convention.","Add a test that scans bean classes for lifecycle annotations and asserts zero parameters.","Inject collaborators via field/constructor, never via lifecycle-method parameters."],"tags":["spring","lifecycle","postconstruct","configuration"],"analyzedSha":"e8729d043887bf0d0baf91e062e909b56eb2b708","analyzedAt":"2026-08-04T19:07:39.725Z","schemaVersion":2}