spring-projects / spring-projects/spring-framework
Inconsistent Behavior of BeanPostProcessor Between Singleton and Prototype Scopes
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 60.2k
- Forks
- 38.8k
- Avg merge
- 5d 2h
- Merged PRs (30d)
- 27
Description
Description
I noticed that the behavior of a BeanPostProcessor varies depending on its scope, which is quite confusing:
- Singleton Scope (Default)
- The processor works correctly for all other beans.
- The processor itself does NOT get processed by its own
postProcessBeforeInitialization/postProcessAfterInitializationmethods.
This happens because the BeanPostProcessor bean is instantiated early during BeanPostProcessor registration, then stored in the singleton pool.
Later, when other non-lazy-init singleton beans are created, since this processor already exists in the singleton pool, its lifecycle is not re-executed, so it does not process itself.
- Prototype Scope (
@Scope("prototype"))
- The processor works correctly for all other beans (including beans created after the processor is instantiated).
- The processor itself DOES get processed by its own
postProcessBeforeInitialization/postProcessAfterInitializationmethods.
This happens because the prototype-scoped BeanPostProcessor is not cached in the singleton pool. Every time it is created, it goes through the full bean lifecycle, which causes the BeanPostProcessor to apply its own post-processing to itself.
This leads to inconsistent behavior: the same BeanPostProcessor exhibits different lifecycle callback behavior based on its scope.
This inconsistency is not mentioned in the official documentation, which can lead to unexpected and confusing results for developers.
Steps to Reproduce
- Define a class
UserBeanPostProcessorthat implementsBeanPostProcessorand logs in both callback methods. - Mark it with
@Component(default singleton scope). - Run the application: logs show the processor works for other beans, but no logs for itself.
- Add
@Scope("prototype")to the processor. - Run the application: logs show the processor works for other beans and processes itself.
Expected Behavior
The behavior should be consistent across both scopes:
- Either the processor never processes itself (in both singleton and prototype), or
- The processor always processes itself consistently, with clear documentation about the recursion risks.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the reported UserBeanPostProcessor reproduction and compare the singleton and @Scope("prototype") creation paths during BeanPostProcessor registration. Trace the lifecycle callbacks for the processor itself and verify the chosen behavior with coverage for both scopes; done means the behavior is consistent or clearly documented, including recursion risks.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, spring
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100