Injecting spring bean in a JPA Entity Listener

随声附和 提交于 2019-12-12 14:38:42

问题


Am trying to make a JPA Entity Listener aware of the spring context by marking it as @Configurable. But the injected spring beans are null. Am able to make JPA entities aware of the Spring context using the same technique. Am using Spring(core and data-jpa) as infrastructure. Any ideas on how to acheive this using JPA Entity Listeners or 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());
            });
    }
}

and the BaseAggregateRoot code

@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;
}

回答1:


Event Listener mechanism is a JPA concept and is implemented by the JPA provider. I don't think Spring creates event listener class instances - they are rather created by the JPA provider (Hibernate, EclipseLink, etc.). Therefore, the regular Spring injection would not work with event listener class instances. The author of this post seems to have come to the same conclusion.


That said, I do use Spring managed beans in JPA event listeners. The solution I use was developed to get hold of Spring bean instances in all classes that are not managed by Spring. It involves creating the following class:

@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); }
}

This class caches the Spring application context at initial load. The context is then used to look up Spring managed beans.

Using the class is then as simple as SpringApplicationContext.getBean(FooService.class).

All the usual Spring semantics, such as, bean lifecycle, bean scope and transitive dependencies are taken care of.



来源:https://stackoverflow.com/questions/28215030/injecting-spring-bean-in-a-jpa-entity-listener

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!