我试图通过将 JPA 实体侦听器标记为 @Configurable 来使其了解 Spring 上下文。但注入的 spring beans 为空。我能够使用相同的技术使 JPA 实体了解 Spring 上下文。我使用 Spring(核心和 data-jpa)作为基础设施。关于如何使用 JPA 实体监听器或 spring data-jpa 实现此目的有什么想法吗?
@Configurable
@Scope("singleton")
public class AggregateRootListener {
private static Logger log = LoggerFactory.getLogger(AggregateRootListener.class);
@Autowired
private EventHandlerHelper eventHandlerHelper;
@PostPersist
@PostUpdate
public void publishEvents(BaseAggregateRoot aggregateRoot){
log.info(aggregateRoot.getEvents().toString());
aggregateRoot.getEvents().stream()
.forEach(event -> {
eventHandlerHelper.notify(event, aggregateRoot);
log.info("Publishing " + event + " " + aggregateRoot.toString());
});
}
}
和 BaseAggregateRoot 代码
@Configurable
@Scope("prototype")
@MappedSuperclass
@EntityListeners(AggregateRootListener.class)
public abstract class BaseAggregateRoot extends BaseDomain{
public static enum AggregateStatus {
ACTIVE, ARCHIVE
}
@EmbeddedId
@AttributeOverrides({
@AttributeOverride(name = "aggregateId", column = @Column(name = "ID", nullable = false))})
protected AggregateId aggregateId;
@Version
private Long version;
}
事件监听器机制是一个JPA概念,由JPA提供者实现。我不认为 Spring 创建事件监听器类实例 - 它们是由 JPA 提供者(Hibernate、EclipseLink 等)创建的。因此,常规 Spring 注入不适用于事件侦听器类实例。 这篇文章的作者似乎也得出了同样的结论。
也就是说,我确实在 JPA 事件侦听器中使用 Spring 托管 bean。我使用的解决方案是为了获取不受 Spring 管理的所有类中的 Spring bean 实例而开发的。它涉及创建以下类:
@Component
public class SpringApplicationContext implements ApplicationContextAware {
private static ApplicationContext CONTEXT;
public void setApplicationContext(final ApplicationContext context)
throws BeansException {
CONTEXT = context;
}
public static <T> T getBean(Class<T> clazz) { return CONTEXT.getBean(clazz); }
}
此类在初始加载时缓存 Spring 应用程序上下文。然后使用上下文来查找 Spring 托管 bean。
使用该类就像
SpringApplicationContext.getBean(FooService.class)
一样简单。
所有常见的 Spring 语义,例如 bean 生命周期、bean 作用域和传递依赖关系都得到处理。
我知道这个问题是老问题,但它可能会帮助任何想要解决同一问题的人。我最近遇到了同样的问题,发现自从 Spring V5.1(和 Hibernate V5.3)以来,它应该开箱即用,因为 Spring 注册为这些类的提供者。文档链接https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/orm/hibernate5/SpringBeanContainer.html
因此,如果您在 springboot 中使用 springv5.1,只需将 EntityListener 声明为 @component 并自动装配 spring beans。