我已经习惯了使用Spring做我的依赖注入,像这样:使用Hibernate 4的集成模式和Spring的依赖注入
<context:component-scan base-package="org.emmerich.myapp" />
,然后标注我的依赖类与Autowired
像这样:
public class DependentClass {
@Autowired
private Dependency dependency;
}
但是,随着Hibernate 4.0的变化,我们现在建议使用新的Integrator
接口进行服务发现。这包括为触发器添加事件侦听器,如postUpdate
,postDelete
等。
不幸的是,这并不能很好地通过注释依赖关系进行依赖注入。我有以下设置:
我已定义的集成商将我的收听者添加到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
}
}
不幸的是,如评论所示,这是行不通的。我想这是因为我在MyIntegrator
里实例化了MyListener
,它没有拿起组件,也没有自动装配组件。但是,如果我尝试这样做:
@Component
public class MyIntegrator {
@Autowired
private MyListener listener;
...
}
然后,侦听器不是自动装配的。
首先,使用Spring必须做new MyListener()
时感觉不对。我希望能够将它定义为自动装配的依赖关系,并让Spring为我创建一个单例。我的问题是这样的:
在新的Integrator接口中使用依赖注入的最佳方法是什么?集成器用于构建SessionFactory,因此当它们被要求集成它们自己时,我认为没有可用的应用程序上下文。因此,我需要在集成器中需要的所有bean都需要以“老式”方式创建,并且不会收到它们的自动装配。
我对春天的世界很陌生,你会说这是我应该期待看到的东西吗?我知道当我在SessionFactory中时,我处于应用程序的不同范围中,但是有没有办法获得对bean的引用并启用自动装配,即使我通过new
创建它?
我想出的解决方案使用了ApplicationContextAware
。这意味着只要上下文可用,MyListener
就会收到对ApplicationContext
的引用,并且我从方法调用的上下文中引用了bean,而不是bean的构造。创建具有new
豆不限制这一点,所以春天仍然给我的应用程序上下文:
@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);
}
}
有没有更好的办法?
你没忘了组件扫描'MyIntegrator '你的'@ Autowired'例子中的类?另外,谁正在实例化MyIntegrator类? –
这也是我提出的完全相同的解决方案。它的工作很好,但静态applicationcontext只是觉得有点肮脏:)我只是没有找到一个更好的方式,因为休眠创建集成器。一旦我有时间,我想让这个更抽象,并有一个集成商,这只是一个链接,可以注册春天创建的监听器等。我发现了一次博客,但我现在不记得这个网址。 –
@SotiriosDelimanolis Hibernate为你创建'Integrator'。您可以在META-INF/services目录中指定一个文本文件,指向您要实例化的集成器列表,Hibernate会在创建SessionFactory之前为您创建它们。我有点理解无法在Integrator中使用Autowire组件 - 它是在应用程序范围之外构建的。不过,我认为可以在侦听器中使用@Autowired。是的,我在上下文中扫描涉及的所有类。 – EMMERICH