通过预实例化+预转换,解决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