Spring将Singleton Bean注入Prototype Bean导致Singleton重复创建
First off, let's clarify a key point: injecting a singleton bean into a prototype bean is not inherently problematic in Spring. By default, Spring should inject the same singleton instance into every new prototype bean you create. The fact that your RangeFilteringParams (supposed singleton) is being reinitialized (with init filtering printing multiple times and changing IDs) means something is overriding this default behavior.
Let's walk through the most likely causes and fixes:
1. Verify Your Singleton's Scope Configuration
While @Component defaults to singleton scope, it's possible (though unlikely) that some other configuration is overriding this. Explicitly declare the scope to eliminate ambiguity:
@Component("rangeFilteringParams") @Scope("singleton") // Explicitly enforce singleton scope public class RangeFilteringParams { // Your existing fields, @PostConstruct, getters/setters, etc. }
2. Check for Duplicate Bean Definitions
Spring will create multiple instances of a bean if there are multiple definitions for it. Look for these scenarios:
- Did you define
RangeFilteringParamsboth with@Componentand in a@Configurationclass using@Bean("rangeFilteringParams")? This would register two separate beans with the same name, leading to unexpected instances. - Is
RangeFilteringParamsbeing scanned by multiple@ComponentScanannotations? If your application has overlapping scan paths, the bean might be registered multiple times.
To debug this, you can print all bean definitions at startup to check for duplicates:
@Autowired private ApplicationContext context; // Somewhere in your startup logic for (String beanName : context.getBeanDefinitionNames()) { if (beanName.equals("rangeFilteringParams")) { System.out.println("Found bean: " + beanName + ", type: " + context.getBean(beanName).getClass()); System.out.println("Bean instance ID: " + System.identityHashCode(context.getBean(beanName))); } }
3. Ensure You're Fetching the Prototype Bean Correctly
If you're manually instantiating FilteringWorkerPaired (e.g., new FilteringWorkerPaired()), Spring won't manage that instance, and the @Inject annotation won't work as expected. Instead, you must fetch the prototype bean from the Spring context every time you need a new instance:
@Autowired private ApplicationContext context; // When you need a new worker instance FilteringWorkerPaired worker = context.getBean("filterWorkerPaired", FilteringWorkerPaired.class);
This ensures Spring properly injects the singleton RangeFilteringParams into each new prototype worker.
4. Rule Out Proxying Confusion
If your RangeFilteringParams is being proxied (e.g., for AOP), the instance ID you see might be the proxy's ID instead of the target singleton. However, the @PostConstruct method should still only run once for the actual singleton instance. If you're seeing init filtering printed multiple times, this confirms multiple actual instances are being created—so proxying isn't the root cause here.
Final Takeaway
Injecting a singleton into a prototype is a valid pattern. Your issue stems from unintended multiple instantiation of your "singleton" bean, not the injection pattern itself. Start with verifying the scope and checking for duplicate bean definitions, as those are the most common culprits.
内容的提问来源于stack exchange,提问作者Sam

