EMM*_*ICH 8 java spring hibernate spring-mvc inversion-of-control
我习惯使用Spring来执行依赖注入,如下所示:
<context:component-scan base-package="org.emmerich.myapp" />
Run Code Online (Sandbox Code Playgroud)
然后用Autowired这样注释我的依赖类:
public class DependentClass {
@Autowired
private Dependency dependency;
}
Run Code Online (Sandbox Code Playgroud)
但是,随着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);
}
Run Code Online (Sandbox Code Playgroud)
我也定义了类MyListener,它看起来像你典型的事件监听器.
@Component
public class MyListener implements PostInsertEventListener {
@Autowired
private Dependent dependent;
public void onPostInsert(PostInsertEvent event) {
// dependent == null
}
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,正如评论所示,这不起作用.我想这是因为我在MyListener内部实例化MyIntegrator,它不会拾取组件而不会自动装配组件.但是,如果我试试这个:
@Component
public class MyIntegrator {
@Autowired
private MyListener listener;
...
}
Run Code Online (Sandbox Code Playgroud)
然后听众没有自动装配.
首先,使用Spring必须要做的事情感觉不对new MyListener().我希望能够将其定义为自动连接的依赖项,并让Spring为我创建一个单例.我的问题是:
在新的Integrator接口中使用依赖注入的最佳方法是什么?集成器用于构建SessionFactory,因此当他们被要求集成自己时,我猜没有可用的应用程序上下文.因此,我在Integrator中需要的任何bean都需要以"老式"方式创建,并且不会在它们上接收自动装配.
我对Spring这个世界很陌生,你会说这是我应该期待看到的吗?我知道当我在SessionFactory时,我处于应用程序的不同范围,但是有没有办法获得对bean的引用并启用autowire,即使我是通过它创建它new?
我想出的解决方案ApplicationContextAware.这意味着每当上下文可用时都会MyListener收到对引用的引用ApplicationContext,并且我在方法调用的上下文中引用了bean,而不是bean构造.创建一个bean new并不限制它,所以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);
}
}
Run Code Online (Sandbox Code Playgroud)
有没有更好的办法?
Mar*_*rey 12
正如评论中所述,我采用了另一种集成Spring托管的HibernateEventListeners的方法.这是代码:
Spring托管的Hibernate事件侦听器的标识符接口:
public interface HibernateEventListener { }
Run Code Online (Sandbox Code Playgroud)
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<HibernateEventListener> 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.
}
}
}
Run Code Online (Sandbox Code Playgroud)
"登记处":
@Component
public class HibernateSpringIntegratorRegistry {
@Autowired(required = false)
private List<HibernateEventListener> hibernateEventListeners;
public List<HibernateEventListener> getHibernateEventListeners() {
if (hibernateEventListeners == null) {
return Collections.emptyList();
}
return hibernateEventListeners;
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个示例实现:
@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();
...
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10755 次 |
| 最近记录: |