EntityListener中@Autowired注入Bean遇空指针问题求助
解决JPA EntityListener中Spring Bean注入NullPointerException的方案
核心原因
JPA的EntityListener实例是由JPA容器(如Hibernate)创建的,不属于Spring容器管理范畴,所以直接用@Autowired注入Spring Bean会失效——哪怕加了@Component或者继承SpringBeanAutowiringSupport也没用,因为Spring管不到JPA new出来的对象。
可行方案一:静态工具类获取Spring上下文
这是最直接且无需额外依赖的方案:
- 编写Spring上下文工具类
@Component public class SpringContextUtil implements ApplicationContextAware { private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext context) throws BeansException { applicationContext = context; } public static <T> T getBean(Class<T> beanClass) { return applicationContext.getBean(beanClass); } }
这个类会被Spring初始化,把上下文保存为静态变量,方便后续获取Bean。
- 修改EntityListener代码
去掉@Autowired,在需要用到Bean的方法里通过工具类获取,同时把@PostUpdate标注的方法改成public(JPA需要能访问到这个方法,private会导致触发失败):
public class EListener { @PostUpdate public void afterUpdate(Elab elab){ CacheService cacheService = SpringContextUtil.getBean(CacheService.class); LockHandler handler = SpringContextUtil.getBean(LockHandler.class); final DSTate state1 = cacheService.getAllStates().stream() .filter(x -> x.getId().equals(elab.getFkState())).findFirst().orElse(new DState()); handler.sendMessage(state1); } }
可行方案二:用@Configurable+AspectJ织入
这个方案让Spring接管JPA创建的EntityListener实例,需要启用AspectJ织入:
- 启用Spring配置支持
在项目启动类上添加@EnableSpringConfigured注解:
@SpringBootApplication @EnableSpringConfigured public class YourApplication { public static void main(String[] args) { SpringApplication.run(YourApplication.class, args); } }
- 修改EntityListener
给类加上@Configurable和@Component,同时确保@PostUpdate方法是public:
@Component @Configurable public class EListener { @Autowired private LockHandler handler; @Autowired private CacheService cacheService; @PostUpdate public void afterUpdate(Elab elab){ final DSTate state1 = cacheService.getAllStates().stream() .filter(x -> x.getId().equals(elab.getFkState())).findFirst().orElse(new DState()); handler.sendMessage(state1); } }
- 添加AspectJ依赖
如果是Maven项目,在pom.xml中加入:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> </dependency>
额外注意事项
- 确认
LockHandler和CacheService已经被Spring管理:类上要加@Service/@Component等注解,且在Spring扫描范围内 - 不要把
@PostUpdate方法设为private,JPA代理类无法访问private方法,会导致监听逻辑不触发
内容的提问来源于stack exchange,提问作者boh
相关产品推荐
相关产品推荐

