1、SharedEntityManagerCreator: entitymanager的創建入口
該類被EntityManagerBeanDefinitionRegistrarPostProcessor注冊到beanfactory中,依賴EntityManager bean實例的,
都會調用該類的工廠方法createSharedEntityManager,而該工廠方法的參數是EntityManagerFactory,通過BeanDefinitionUtils
找到類型為“EntityManagerFactory.class, AbstractEntityManagerFactoryBean.class”的所有BeanDefinition,針對找到的每個
BeanDefinition,注冊一個EntityManager的BeanDefinition
public class EntityManagerBeanDefinitionRegistrarPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { for (EntityManagerFactoryBeanDefinition definition : getEntityManagerFactoryBeanDefinitions(beanFactory)) { if (!(definition.getBeanFactory() instanceof BeanDefinitionRegistry)) { continue; } BeanDefinitionBuilder builder = BeanDefinitionBuilder .rootBeanDefinition("org.springframework.orm.jpa.SharedEntityManagerCreator"); builder.setFactoryMethod("createSharedEntityManager"); builder.addConstructorArgReference(definition.getBeanName()); AbstractBeanDefinition emBeanDefinition = builder.getRawBeanDefinition(); emBeanDefinition.addQualifier(new AutowireCandidateQualifier(Qualifier.class, definition.getBeanName())); emBeanDefinition.setScope(definition.getBeanDefinition().getScope()); emBeanDefinition.setSource(definition.getBeanDefinition().getSource()); BeanDefinitionReaderUtils.registerWithGeneratedName(emBeanDefinition, (BeanDefinitionRegistry) definition.getBeanFactory()); } } }
2、JpaMetamodelMappingContextFactoryBean用來生成JpaMetamodelMappingContext
該FactoryBean創建實例時,遍歷所有的EntityManagerFactory,調用EntityManagerFactory.getMetamodel,
將所有的Metamodel加入到一個集合,然后傳入JpaMetamodelMappingContext,在將來創建Entity時使用。
class JpaMetamodelMappingContextFactoryBean extends AbstractFactoryBean<JpaMetamodelMappingContext> implements ApplicationContextAware { private ListableBeanFactory beanFactory; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.beanFactory = applicationContext; } @Override public Class<?> getObjectType() { return JpaMetamodelMappingContext.class; } @Override protected JpaMetamodelMappingContext createInstance() throws Exception { Set<Metamodel> models = getMetamodels(); Set<Class<?>> entitySources = new HashSet<Class<?>>(); for (Metamodel metamodel : models) { for (ManagedType<?> type : metamodel.getManagedTypes()) { Class<?> javaType = type.getJavaType(); if (javaType != null) { entitySources.add(javaType); } } } JpaMetamodelMappingContext context = new JpaMetamodelMappingContext(models); context.setInitialEntitySet(entitySources); context.initialize(); return context; } private Set<Metamodel> getMetamodels() { Collection<EntityManagerFactory> factories = BeanFactoryUtils.beansOfTypeIncludingAncestors(beanFactory, EntityManagerFactory.class).values(); Set<Metamodel> metamodels = new HashSet<Metamodel>(factories.size()); for (EntityManagerFactory emf : factories) { metamodels.add(emf.getMetamodel()); } return metamodels; } }
3、JpaRepository中的EntityManager的注入也是通過SharedEntityManagerCreator的工廠方法創建的。
參見JpaRepositoryConfigExtension.getEntityManagerBeanDefinitionFor
4、PersistenceAnnotationBeanPostProcessor: 用來處理persistencecontext,persistenceunit兩個注解
直接調用SharedEntityManagerCreator的createSharedEntityManager方法用來注入EntityManager,
位於PersistenceAnnotationBeanPostProcessor$PersistenceElement類內。
5、JpaRepositoryFactoryBean: 創建JpaRepository的工廠類, 實際委托給JpaRepositoryFactory類執行
在創建JpaRepositoryFactory時,通過加入TransactionalRepositoryProxyPostProcessor,在創建JpaRepository過程中
加入TransactionInterceptor,執行JpaRepository方法時,會自動加入事務處理。TransactionInterceptor中會注入配置的
TransactionManager(比如JpaTransactionManager)
6、EntityManager不是線程安全的,EntityManagerFactory是線程安全的
所以需要每次都在線程中生成新的EntityManager。因為注入到容器的EntityManager是個Proxy,所有的調用會委托給
SharedEntityManagerInvocationHandler去處理,間接的實現了線程安全。
7、TransactionSynchronizationManager: 使用ThreadLocal保存事務資源
8、直接通過注入EntityManger執行查詢或者保存操作的,由於注入的EntityManager是SharedEntityManagerInvocationHandler的Proxy,
會通過EntityManagerFactoryUtils.doGetTransactionalEntityManager獲取已經存在的事務的EntityManager,如果不存在,則會創建一個
EntityManager(有疑問),等調用結束,關閉該EntityManager。
參考: