在 JPA 实体监听器中注入 spring bean

问题描述 投票:0回答:2

我试图通过将 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;
}
spring jpa aspectj spring-data-jpa
2个回答
11
投票

事件监听器机制是一个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 作用域和传递依赖关系都得到处理。


0
投票

我知道这个问题是老问题,但它可能会帮助任何想要解决同一问题的人。我最近遇到了同样的问题,发现自从 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。

© www.soinside.com 2019 - 2024. All rights reserved.