【问题标题】:Injecting spring bean in a JPA Entity Listener在 JPA 实体监听器中注入 spring bean
【发布时间】:2015-01-29 12:40:43
【问题描述】:

我试图通过将 JPA 实体侦听器标记为 @Configurable 来了解 Spring 上下文。但是注入的spring beans是空的。能够使用相同的技术使 JPA 实体了解 Spring 上下文。我使用 Spring(core and data-jpa) 作为基础设施。关于如何使用 JPA Entity Listeners 或 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


【解决方案1】:

Event Listener 机制是一个 JPA 概念,由 JPA 提供者实现。我不认为 Spring 创建事件侦听器类实例——它们是由 JPA 提供程序(Hibernate、EclipseLink 等)创建的。因此,常规 Spring 注入不适用于事件侦听器类实例。 this post的作者似乎也得出了同样的结论。


也就是说,我确实在 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 范围和传递依赖项。

【讨论】:

  • 与简单地将ApplicationContext 注入所需位置相比,这种抽象有什么好处?
  • @WillFaithfull,这是针对非 Spring 管理的 bean 的类需要 Spring 管理的 bean 实例的情况。在这种情况下,自动装配将不起作用,因为消费者类不是由 Spring 管理的。
  • 哦,现在我明白了 - 我没有注意到 static 修饰符。现在说得通了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-07-01
  • 2020-07-20
  • 1970-01-01
  • 2011-05-07
  • 1970-01-01
  • 2012-07-25
  • 1970-01-01
相关资源
最近更新 更多