spring mongodb converter

通过预实例化+预转换,解决Spring Data MongoDB 在首次加载实体类时的反射初始化锁问题

问题所在:

当你使用spring data mongodb的api操作mongodb时,例如 mongoTemplagte.findbyId()

该方法内部会去调用

MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);

而getPersistentEntity这个方法会加写锁去注册 TypeInformation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
@Nullable
@Override
public E getPersistentEntity(TypeInformation<?> type) {

Assert.notNull(type, "Type must not be null");

try {

read.lock();

Optional<E> entity = persistentEntities.get(type);

if (entity != null) {
return entity.orElse(null);
}

} finally {
read.unlock();
}

if (!shouldCreatePersistentEntityFor(type)) {

try {
write.lock();
persistentEntities.put(type, NONE);
} finally {
write.unlock();
}

return null;
}

if (strict) {
throw new MappingException("Unknown persistent entity " + type);
}

return addPersistentEntity(type).orElse(null);
}


------------------------//addPersistentEntity //---------------------------------

/**
* Adds the given {@link TypeInformation} to the {@link MappingContext}.
*
* @param typeInformation must not be {@literal null}.
* @return
*/
protected Optional<E> addPersistentEntity(TypeInformation<?> typeInformation) {

Assert.notNull(typeInformation, "TypeInformation must not be null");

try {

read.lock();

Optional<E> persistentEntity = persistentEntities.get(typeInformation);

if (persistentEntity != null) {
return persistentEntity;
}

} finally {
read.unlock();
}

E entity;

try {

write.lock();

Optional<E> userTypeEntity = persistentEntities.get(typeInformation.getUserTypeInformation());

if (userTypeEntity != null) {
persistentEntities.put(typeInformation, userTypeEntity);
return userTypeEntity;
}

entity = doAddPersistentEntity(typeInformation);

} catch (BeansException e) {
throw new MappingException(e.getMessage(), e);
} finally {
write.unlock();
}

// Inform listeners
if (applicationEventPublisher != null) {
applicationEventPublisher.publishEvent(new MappingContextEvent<>(this, entity));
}

return Optional.of(entity);
}

而jdk的写锁就有问题

获取写锁失败的线程会一直阻塞,而不是直接返回

总结:

通过「预实例化 + 预转换」的办法,解决了 Spring Data MongoDB 在首次加载实体类时的反

射初始化锁问题,提升了项目首次数据访问时的并发性能

解决方案:

ps:https://blog.csdn.net/dch9210/article/details/116131039