Spring Data MongoDB 教程

生命周期事件

MongoDB 映射框架包括几个 org.springframework.context.ApplicationEvent 事件,您的应用程序可以通过在 ApplicationContext 中注册特殊的 bean 来响应这些事件。

实体的生命周期事件可能是昂贵的,当加载大型结果集时,你可能会注意到性能的变化。此时,你可以在 MongoTemplate API 上通过 setEntityLifecycleEventsEnabled() 方法去停用生命周期事件。

如果要在一个对象通过转换过程(将你的域对象变成 org.bson.Document)之前拦截它,你可以注册一个 AbstractMongoEventListener 的子类,重写 onBeforeConvert() 方法。当事件被派发时,你的自定义监听器将被调用,并在域对象进入转换器之前传递给它。如下例:

public class BeforeConvertListener extends AbstractMongoEventListener<Person> {

   @Override
   public void onBeforeConvert(BeforeConvertEvent<Person> event) {
       // ... does some auditing manipulation, set timestamps, whatever ...
   }

}

如果为了在对象进入数据库之前对其进行拦截,你可以注册一个 org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener 的子类,重写 onBeforeSave() 方法。当事件被派发时,你自定义的监听器将被调用并传递给域对象和转换后的 com.mongodb.Document。如下例:

public class BeforeSaveListener extends AbstractMongoEventListener<Person> {

   @Override
   public void onBeforeSave(BeforeSaveEvent<Person> event) {
       // ... change values, delete them, whatever ...
   }

}

注意:如果在你的 Spring ApplicationContext 中声明这些 Bean,会使它们在事件被分派时被调用。

AbstractMappingEventListener 类存在以下几个回调方法:

  • onBeforeConvert: 在 MongoTemplate 的 insert、insertList 和 save 操作中,在对象被 MongoConverter 转换为 Document 之前被调用。

  • onBeforeSave: 在数据库中插入或保存 Document 之前,在 MongoTemplate 的 insert、insertList 和 save 操作中被调用。

  • onAfterSave: 在数据库中插入或保存 Document 之后,在 MongoTemplate 的 insert、insertList 和 save 操作中被调用。

  • onAfterLoad: 在 MongoTemplate 的 find、findAndRemove、findOne 和 getCollection 方法中,在 Document 被从数据库中检索出来后被调用。

  • onAfterConvert: 在 MongoTemplate 的 find、findAndRemove、findOne 和 getCollection 方法中,在 Document 从数据库中检索出来并转换为 POJO 之后被调用。

生命周期事件只针对根级类型发射,在文档根中作为属性使用的复杂类型不受事件发布的影响,除非它们是用 @DBRef 注解的文档引用。

警告:生命周期事件依赖于 ApplicationEventMulticaster,在 SimpleApplicationEventMulticaster 的情况下,它可以用 TaskExecutor 来配置,因此在事件被处理时没有保证。

完整示例

(1)application.properties 配置文件

# Log
logging.level.root=debug

# MongoDB
spring.data.mongodb.uri=mongodb://localhost:27017/test

(2)AppConfig.java 配置类,配置 MongoTemplate 对象

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.data.mongodb.core.MongoTemplate;

/**
* 配置 MongoTemplate
* @author hxstrive.com 2022/12/23
*/
@Slf4j
@Configuration
public class AppConfig {

   @Bean
   public MongoTemplate mongoTemplate(MongoDatabaseFactory mongoDatabaseFactory) {
       log.info("mongoTemplate({}, {})", mongoDatabaseFactory);
       return new MongoTemplate(mongoDatabaseFactory);
   }

}

(3)集合 person 对应的实体

import lombok.Builder;
import lombok.Data;
import lombok.ToString;

@Data
@ToString
@Builder
public class Person {
   /** 用户ID */
   private int id;
   /** 用户姓名 */
   private String name;
   /** 年龄 */
   private int age;
}

(4)自定义监听器

import com.hxstrive.springdata.mongodb.entity.Person;
import org.springframework.data.mongodb.core.mapping.event.*;
import org.springframework.stereotype.Component;

/**
* 实现 Mongo 事件监听器
* @author hxstrive.com
*/
@Component
public class MyMongoEventListener extends AbstractMongoEventListener<Person> {

   @Override
   public void onApplicationEvent(MongoMappingEvent<?> event) {
       super.onApplicationEvent(event);
       System.out.println("onApplicationEvent() " + event);
   }

   @Override
   public void onBeforeConvert(BeforeConvertEvent<Person> event) {
       super.onBeforeConvert(event);
       System.out.println("onBeforeConvert() " + event);
   }

   @Override
   public void onBeforeSave(BeforeSaveEvent<Person> event) {
       super.onBeforeSave(event);
       System.out.println("onBeforeSave() " + event);
   }

   @Override
   public void onAfterSave(AfterSaveEvent<Person> event) {
       super.onAfterSave(event);
       System.out.println("onAfterSave() " + event);
   }

   @Override
   public void onAfterLoad(AfterLoadEvent<Person> event) {
       super.onAfterLoad(event);
       System.out.println("onAfterLoad() " + event);
   }

   @Override
   public void onAfterConvert(AfterConvertEvent<Person> event) {
       super.onAfterConvert(event);
       System.out.println("onAfterConvert() " + event);
   }

   @Override
   public void onAfterDelete(AfterDeleteEvent<Person> event) {
       super.onAfterDelete(event);
       System.out.println("onAfterDelete() " + event);
   }

   @Override
   public void onBeforeDelete(BeforeDeleteEvent<Person> event) {
       super.onBeforeDelete(event);
       System.out.println("onBeforeDelete() " + event);
   }
}

(5)客户端代码,说明见注释。

import com.hxstrive.springdata.mongodb.entity.Person;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.mongodb.core.MongoTemplate;

@SpringBootTest
class ListenerDemo1 {

   @Autowired
   private MongoTemplate mongoTemplate;

   @Test
   void save() {
       mongoTemplate.save(Person.builder().id(100).name("Helen").age(28).build());
       // 回调:
       // onBeforeConvert() org.springframework.data.mongodb.core.mapping.event.BeforeConvertEvent[source=Person(id=100, name=Helen, age=28)]
       // onApplicationEvent() org.springframework.data.mongodb.core.mapping.event.BeforeConvertEvent[source=Person(id=100, name=Helen, age=28)]
       // onBeforeSave() org.springframework.data.mongodb.core.mapping.event.BeforeSaveEvent[source=Person(id=100, name=Helen, age=28)]
       // onApplicationEvent() org.springframework.data.mongodb.core.mapping.event.BeforeSaveEvent[source=Person(id=100, name=Helen, age=28)]
       // onAfterSave() org.springframework.data.mongodb.core.mapping.event.AfterSaveEvent[source=Person(id=100, name=Helen, age=28)]
       // onApplicationEvent() org.springframework.data.mongodb.core.mapping.event.AfterSaveEvent[source=Person(id=100, name=Helen, age=28)]
   }

}
说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号