项目中想记录操作日志,也就是针对一些关键的信息的操作,进行日志的记录。首先考虑到的就是在数据变更的时候能得到通知,然后去做变更信息的记录操作。项目中使用的hibernate4,于是上网查了一下,发现在hibernate支持interceptor和listener,但是interceptor是在操作前拦截。这个显然并不合适。操作前拦截的话,如果已经记录完了操作日志,结果数据操作并没成功怎么办?是否能回滚?总之感觉不太合适。listener是满合适的。晚上很多的介绍,但是都是基于hibernate3以前版本的,都是说在spring配置sessionFactory的时候,加个eventListeners的属性就可以了。而hibernate4中已经完全变了,spring对hibernate4也不支持eventListener属性了。网上搜来搜去,国人针对hibernate4这个改变的解决办法几乎没有。于是查看官方文档。发现在hibernate4中,listener的注册是通过Integrator来完成的,而Integrator是通过服务来发布的。需要在配置META-INF/services/org.hibernate.integrator.spi.Integrator文件中。但是这种方式,在listener中就无法使用spring的依赖注入,因为他们根本不在spring容器内。还好,sessionFactory中是可以获得到注册对象的。那么我们只要再应用启动的时候,当spring环境准备好以后,在完成hibernate监听的注册就ok了。

我的实现方法是这样的:编写监听注册类:

 
  
  1. public class ListenersImpl implements IListeners  
  2. {  
  3.     private List<AlterationListener> listeners;  
  4.       
  5.     private SessionFactory sessionFactory;  
  6.       
  7.     private static final Logger logger = LoggerFactory.getLogger(ListenersImpl.class);  
  8.       
  9.     public void setSessionFactory(SessionFactory sessionFactory)  
  10.     {  
  11.         this.sessionFactory = sessionFactory;  
  12.     }  
  13.  
  14.     public void setListeners(List<AlterationListener> listeners)  
  15.     {  
  16.         this.listeners = listeners;  
  17.     }  
  18.  
  19.     public void registerListeners()  
  20.     {  
  21.         EventListenerRegistry registry  = ((SessionFactoryImpl)sessionFactory).getServiceRegistry().getService(EventListenerRegistry.class);  
  22.         for(AlterationListener listener : listeners)  
  23.         {  
  24.             registry.getEventListenerGroup(EventType.POST_INSERT).appendListener(listener);  
  25.             registry.getEventListenerGroup(EventType.POST_UPDATE).appendListener(listener);  
  26.             registry.getEventListenerGroup(EventType.POST_DELETE).appendListener(listener);  
  27.             logger.info("register hibernate listener : {} operation : [insert, update, delete]", listener.getClass().getName());  
  28.         }  
  29.     }  

在系统启动类中添加方法:

 
  
  1. public static void startHibernateListeners()  
  2.     {  
  3.         if(applicationContext != null)  
  4.         {  
  5.             IListeners listeners = (IListeners)applicationContext.getBean("com.xk.commons.hibernate.listener.IListeners");  
  6.             listeners.registerListeners();  
  7.         }  
  8.     } 

这个方法中用到了Spring容器applicationContext,也就是说,调用这个方法的时机必须在spring的环境准备好以后,如下:

 

 
  
  1. String springConfigPath = getSpringConfig();  
  2.     applicationContext = new FileSystemXmlApplicationContext(springConfigPath);  
  3.     logger.info("load spring config file : {}", springConfigPath);  
  4.     startHibernateListeners(); 

上面的代码片段很好理解。下面是我们的监听的相应处理类:

 

 
  
  1. public class AlterationListener implements PostUpdateEventListener, PostInsertEventListener, PostDeleteEventListener  
  2. {  
  3.  
  4.     /**  
  5.      *   
  6.      */  
  7.     private static final long serialVersionUID = 8775069565992961824L;  
  8.  
  9.     private EventCenter eventCenter;  
  10.  
  11.     public void setEventCenter(EventCenter eventCenter)  
  12.     {  
  13.         this.eventCenter = eventCenter;  
  14.     }  
  15.  
  16.     private String eventType;  
  17.  
  18.     public void setEventType(String eventType)  
  19.     {  
  20.         this.eventType = eventType;  
  21.     }  
  22.  
  23.     public void onPostDelete(PostDeleteEvent event)  
  24.     {  
  25.         // TODO Auto-generated method stub  
  26.  
  27.     }  
  28.  
  29.     public void onPostInsert(PostInsertEvent event)  
  30.     {  
  31.         // TODO Auto-generated method stub  
  32.     }  
  33.  
  34.     public void onPostUpdate(PostUpdateEvent event)  
  35.     {  
  36.         // TODO Auto-generated method stub  
  37.         Event evt = new Event(this, event, eventType);  
  38.         eventCenter.addEvent(evt);  
  39.     }  
  40. }  

可以看到在onPostUpdate方法中,我们进行相应的变更处理就可以了。