Spring中如何在Rest方法内动态实例化事务型组件?
解决方案
要在每次调用接口时生成TestComponent的新实例,同时保证@Transactional注解生效,你可以通过以下步骤实现:
1. 修改TestComponent的作用域为原型
首先将TestComponent的作用域设置为原型(prototype),这样Spring每次请求该Bean时都会创建新实例:
@Scope("prototype") @Component @Transactional public class TestComponent { private EntityManager entityManager; private UUID randomUUID; @Autowired public TestComponent(EntityManager entityManager) { this.entityManager = entityManager; this.randomUUID = UUID.randomUUID(); } public String uuid() { // entityManager transactional stuff return randomUUID.toString(); } }
2. 方式一:使用Provider<TestComponent>获取新实例
在RestController中注入Provider<TestComponent>,每次调用get()方法即可获取新的TestComponent实例,Spring会自动处理事务逻辑:
@Validated @RestController @RequestMapping("test") public class TestController { private final Provider<TestComponent> testComponentProvider; @Autowired public TestController(Provider<TestComponent> testComponentProvider) { this.testComponentProvider = testComponentProvider; } @GetMapping public String test() { TestComponent component = testComponentProvider.get(); return component.uuid(); } }
3. 方式二:使用@Lookup方法注入
通过@Lookup注解实现方法级的Bean注入,Spring会动态生成代理方法,每次调用都会返回新的原型实例:
@Validated @RestController @RequestMapping("test") public class TestController { @GetMapping public String test() { TestComponent component = createTestComponent(); return component.uuid(); } // Spring会代理该方法,返回新的TestComponent实例 @Lookup protected TestComponent createTestComponent() { // 此处仅为占位实现,Spring会自动替换 return null; } }
为什么之前的尝试无效?
- 直接
new TestComponent():该实例不受Spring管理,@Transactional注解无法生效,EntityManager也无法自动注入。 ApplicationContext.getBean():默认情况下TestComponent是单例作用域,所以每次获取同一个实例;若已设置原型作用域,虽然能获取新实例,但直接依赖ApplicationContext不符合依赖注入的设计原则。
内容的提问来源于stack exchange,提问作者Emax
相关产品推荐
相关产品推荐

