不是在构造方法「之前」修饰 Bean、注入;是构造方法跑完之后,才做属性注入,再跑 @PostConstruct。
整个 Bean 生命周期顺序(非常关键):
- 【构造方法】new 对象(实例化,此时对象是半成品,所有 @Resource 字段都还是 null)
- 【属性填充】@Resource 注入
transactionManager - 【@PostConstruct】执行 initTransactionTemplate (),手动 new TransactionTemplate
- 【AOP 后置处理(如有)】生成代理对象(这一步和 transactionTemplate 没关系!)
- Bean 就绪,可以对外提供服务,后面业务方法被调用
java
运行
@Resource
private PlatformTransactionManager transactionManager; // 第2步才注入进来
private TransactionTemplate transactionTemplate;
@PostConstruct
void initTransactionTemplate() {
this.transactionTemplate = new TransactionTemplate(transactionManager); // 第3步
}
👉 transactionManager 是构造方法执行完之后 才注入的,所以必须放到 @PostConstruct 里面去 new template; 构造方法里面直接写是不行的,那时候 transactionManager 还是 null。
然后回答你的后半句:
然后构造方法后调用事务方法的时候使用?
✅ 这点是对的: 等整个 Bean 初始化完成,后续业务方法(比如你那个清理 delete 的方法)被调用时,直接拿已经初始化好的 transactionTemplate 去执行编程式事务。
但是一定要区分两件事:
- 这个
transactionTemplate只是一个本地工具对象,不是用来修饰、改造当前 Service 这个 Bean 的; - 它不会给当前 Service 增加 AOP 代理能力 。
- 这个 template 自己自带事务能力,靠的是里面持有的
transactionManager - 它走编程式事务,不走 AOP 切面,和
@Transactional是两套东西
- 这个 template 自己自带事务能力,靠的是里面持有的
对比一下:
@Transactional:靠 AOP 代理拦截方法,在方法进入 / 退出的时候自动开、提交事务- TransactionTemplate:是一个工具,你主动调用它的 execute 方法,在 lambda 里面手动划定事务范围,不需要 AOP 拦截
一句话修正你的理解
不是构造方法前 注入修饰 Bean; 流程是:构造方法先跑 → 注入 transactionManager → @PostConstruct 初始化 template → 之后业务方法里使用这个 template 做编程式事务。 template 只是一个初始化好的工具,不改造当前 Bean、不生成 AOP 代理。
补充一个容易混淆的点
如果你把代码写成构造注入版本,效果一样,只是时机不同:
java
运行
// 构造注入版本
public YourService(PlatformTransactionManager transactionManager) {
this.transactionTemplate = new TransactionTemplate(transactionManager);
}
这个是构造阶段就初始化 template,但是依然:只是创建工具,不涉及 AOP 代理。 而你贴的代码,选择了属性注入 + @PostConstruct 的写法。