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)] } }