Spring Boot中ObjectFactory创建原型Bean的性能优化问询
解答
测试结果符合预期
纯new操作只是直接调用构造器,无额外逻辑;而Spring的ObjectFactory.getObject()创建原型Bean时,会执行完整的容器管理流程:
- 查找Bean定义
- 实例化依赖的原型Bean(Car、Clothes)
- 处理
@Autowired依赖注入 - 执行生命周期回调(如
@PostConstruct) - 生成AOP代理(若有切面)
这些步骤会带来显著性能开销,因此两者的耗时差异是正常现象。
高效创建原型Bean的优化方案
1. 自定义工厂类,减少Spring容器重复处理
若需保留Spring对依赖的管理,可自定义工厂类手动实例化主Bean,仅让Spring管理依赖创建:
@Component public class EmployeeFactory { @Autowired private ObjectFactory<Car> carFactory; @Autowired private ObjectFactory<Clothes> clothesFactory; public Employee createEmployee() { // 直接调用构造器创建Employee,依赖由Spring提供 return new Employee(carFactory.getObject(), clothesFactory.getObject()); } }
使用时注入EmployeeFactory并调用createEmployee(),跳过Spring对Employee的完整Bean创建流程,性能会比直接用ObjectFactory<Employee>.getObject()提升数倍。
2. 预获取构造器,完全绕过Spring容器流程
若原型Bean不需要Spring的生命周期回调、AOP等特性,可直接获取构造器手动创建所有对象,性能接近纯new:
@Autowired private BeanFactory beanFactory; // 预加载构造器,放在初始化方法中 private Constructor<Employee> employeeConstructor; private Constructor<Car> carConstructor; private Constructor<Clothes> clothesConstructor; @PostConstruct public void initConstructors() throws NoSuchMethodException { employeeConstructor = Employee.class.getConstructor(Car.class, Clothes.class); carConstructor = Car.class.getConstructor(); clothesConstructor = Clothes.class.getConstructor(); } public void start() { var startTime = System.currentTimeMillis(); for (int i = 0; i < 1000000; i++) { try { Car car = carConstructor.newInstance(); Clothes clothes = clothesConstructor.newInstance(); Employee employee = employeeConstructor.newInstance(car, clothes); employee.goToWork(); employees.add(employee); } catch (Exception e) { throw new RuntimeException(e); } } double totalTime = System.currentTimeMillis() - startTime; System.out.println("Optimized Spring seconds: " + totalTime/1000); }
注意:这种方式完全脱离Spring容器管理,后续依赖关系变化需手动修改代码。
3. 调整依赖作用域(业务允许时)
若Car和Clothes不需要每次创建新实例,可将其作用域改为单例(默认就是单例),Spring仅创建一次Car和Clothes实例,每次创建Employee时直接注入这两个单例对象,能大幅降低ObjectFactory.getObject()的耗时。
4. 直接使用BeanFactory获取Bean
ObjectFactory本质是对BeanFactory的委托,直接注入BeanFactory并调用getBean(Employee.class),能减少一层代理开销,性能略优于ObjectFactory.getObject(),但提升幅度有限。
内容的提问来源于stack exchange,提问作者andresmonc
相关产品推荐
相关产品推荐

