使用Hibernate 4的Integrator模式和Spring的dependency injection

我习惯使用Spring来执行dependency injection,如下所示:

 

然后用Autowired注释我的依赖类,如下所示:

 public class DependentClass { @Autowired private Dependency dependency; } 

但是,随着Hibernate 4.0的变化,我们现在建议使用新的Integrator接口进行服务发现。 这包括为postUpdatepostDelete等触发器添加事件监听postDelete

不幸的是,这与通过注释依赖项的dependency injection不能很好地协作。 我有以下设置:

我已定义的集成器将我的监听器添加到ServiceFactory 。 这在META-INF/services/org.hibernate.integrator.spi.Integrator文件中引用。

 public class MyIntegrator implements Integrator { private MyListener listener; public MyIntegrator() { listener = new MyListener(); } @Override public void integrate(Configuration configuration, SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { final EventListenerRegistry eventRegistry = serviceRegistry.getService(EventListenerRegistry.class); eventRegistry.prependListeners(EventType.POST_COMMIT_INSERT, listener); } 

我还定义了MyListener类,它看起来像是典型的事件监听器。

 @Component public class MyListener implements PostInsertEventListener { @Autowired private Dependent dependent; public void onPostInsert(PostInsertEvent event) { // dependent == null } } 

不幸的是,正如评论所示,这不起作用。 我想这是因为我在MyListener实例化MyListener ,它不会拾取组件而不会自动assembly组件。 但是,如果我试试这个:

 @Component public class MyIntegrator { @Autowired private MyListener listener; ... } 

然后听众没有自动assembly。

首先,使用Spring必须执行new MyListener()时感觉不对。 我希望能够将其定义为自动连接的依赖项,并让Spring为我创建一个单例。 我的问题是:

在新的Integrator接口中使用dependency injection的最佳方法是什么? 集成器用于构建SessionFactory,因此当他们被要求集成自己时,我猜没有可用的应用程序上下文。 因此,我在Integrator中需要的任何bean都需要以“老式”方式创建,并且不会在它们上接收自动assembly。

我对Spring这个世界很陌生,你会说这是我应该期待的吗? 我知道当我在SessionFactory时,我处于应用程序的不同范围,但有没有办法获得对bean的引用并启用autowire,即使我是通过new创建它?

我提出的解决方案使用了ApplicationContextAware 。 这意味着只要上下文可用, MyListener收到对ApplicationContext的引用,并且我在方法调用的上下文中引用了bean,而不是bean构造。 用new创建bean并不限制它,所以Spring仍然给我应用程序上下文:

 @Component public class MyListener implements PostInsertEventListener, ApplicationContextAware { private static ApplicationContext context; public void onPostInsert(PostInsertEvent event) { // getDependent() == correct! } public void setApplicationContext(ApplicationContext context) throws BeanException { this.context = context; } public Dependent getDependent() { return context.getBean(Dependent.class); } } 

有没有更好的办法?

正如评论中所述,我采用了另一种集成Spring托管的HibernateEventListeners的方法。 这是代码:

Spring托管的Hibernate事件侦听器的标识符接口:

 public interface HibernateEventListener { } 

HibernateIntegrator:

 @Service public class HibernateSpringIntegrator { private static final Logger log = LoggerFactory.getLogger(HibernateSpringIntegrator.class); @Autowired private HibernateEntityManagerFactory entityManagerFactory; @Autowired private HibernateSpringIntegratorRegistry hibernateSpringIntegratorRegistry; @PostConstruct public void registerListeners() { log.debug("Registering Spring managed HibernateEventListeners"); EventListenerRegistry listenerRegistry = ((SessionFactoryImpl) entityManagerFactory .getSessionFactory()).getServiceRegistry().getService( EventListenerRegistry.class); List eventListeners = hibernateSpringIntegratorRegistry .getHibernateEventListeners(); for (HibernateEventListener hel : eventListeners) { log.debug("Registering: {}", hel.getClass()); if (PreInsertEventListener.class.isAssignableFrom(hel.getClass())) { listenerRegistry.appendListeners(EventType.PRE_INSERT, (PreInsertEventListener) hel); } if (PreUpdateEventListener.class.isAssignableFrom(hel.getClass())) { listenerRegistry.appendListeners(EventType.PRE_UPDATE, (PreUpdateEventListener) hel); } if (PreDeleteEventListener.class.isAssignableFrom(hel.getClass())) { listenerRegistry.appendListeners(EventType.PRE_DELETE, (PreDeleteEventListener) hel); } if (PostInsertEventListener.class.isAssignableFrom(hel.getClass())) { listenerRegistry.appendListeners(EventType.POST_INSERT, (PostInsertEventListener) hel); } if (PostUpdateEventListener.class.isAssignableFrom(hel.getClass())) { listenerRegistry.appendListeners(EventType.POST_UPDATE, (PostUpdateEventListener) hel); } if (PostDeleteEventListener.class.isAssignableFrom(hel.getClass())) { listenerRegistry.appendListeners(EventType.POST_DELETE, (PostDeleteEventListener) hel); } // Currently we do not need other types of eventListeners. Else this method needs to be extended. } } } 

“登记处”:

 @Component public class HibernateSpringIntegratorRegistry { @Autowired(required = false) private List hibernateEventListeners; public List getHibernateEventListeners() { if (hibernateEventListeners == null) { return Collections.emptyList(); } return hibernateEventListeners; } } 

这是一个示例实现:

 @Component public class MailGenerationEventListener implements HibernateEventListener, PostDeleteEventListener, PostInsertEventListener, PostUpdateEventListener { @Override public void onPostDelete(PostDeleteEvent event) { Class entityClass = event.getEntity().getClass(); ... } @Override public void onPostInsert(PostInsertEvent event) { Class entityClass = event.getEntity().getClass(); ... } @Override public void onPostUpdate(PostUpdateEvent event) { Class entityClass = event.getEntity().getClass(); ... } } 

在从hibernate 3.6升级到4.2期间,我们需要通过执行以下配置来使用使用spring-managed bean的自定义validation器: