zoukankan      html  css  js  c++  java
  • Spring JPA实现逻辑源码分析总结

     

    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。

    参考:

    Spring JPA实现逻辑源码分析总结

    从EnableJpaRepository说开去

  • 相关阅读:
    动态加载方法(定时任务)
    安装 asp.net core 出错
    .NET:权限管理
    关于随机数
    博客园首弹
    C# MVC从其他系统获取文件流,显示文件
    Python中操作MySQL步骤
    MySql之_增删改查
    数据库之_SQL注入
    为什么上传到youtube上的视频很模糊
  • 原文地址:https://www.cnblogs.com/yuyutianxia/p/7592719.html
Copyright © 2011-2022 走看看