从EnableJpaRepositories说开去

1 、spring boot

@EnableJpaRepositories(
        repositoryBaseClass = BaseRepositoryImpl.class,
        includeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = BaseRepository.class),
        excludeFilters = @ComponentScan.Filter(NoRepositoryBean.class),
        repositoryFactoryBeanClass = BaseRepositoryFactoryBean.class
)

从EnableJpaRepositories的源代码里面可以看到相关的默认值

 1 @EnableJpaRepositories(
 2     basePackages = {},
 3     basePackageClasses = {},
 4     includeFilters = {},
 5     excludeFilters = {},
 6     repositoryImplementationPostfix = "Impl",
 7     namedQueriesLocation = "",//META-INF/jpa-named-queries.properties
 8     queryLookupStrategy=QueryLookupStrategy.Key.CREATE_IF_NOT_FOUND, //QueryLookupStrategy.Key.x
 9     repositoryFactoryBeanClass=JpaRepositoryFactoryBean.class, //class
10     entityManagerFactoryRef="entityManagerFactory",
11     transactionManagerRef="transactionManager",
12     considerNestedRepositories=false, 
13     enableDefaultTransactions=true
14 )

2、 FilterType 说明

public enum FilterType {

    /**
     * Filter candidates marked with a given annotation.
     * @see org.springframework.core.type.filter.AnnotationTypeFilter
     */
    ANNOTATION,

    /**
     * Filter candidates assignable to a given type.
     * @see org.springframework.core.type.filter.AssignableTypeFilter
     */
    ASSIGNABLE_TYPE,

    /**
     * Filter candidates matching a given AspectJ type pattern expression.
     * @see org.springframework.core.type.filter.AspectJTypeFilter
     */
    ASPECTJ,

    /**
     * Filter candidates matching a given regex pattern.
     * @see org.springframework.core.type.filter.RegexPatternTypeFilter
     */
    REGEX,

    /** Filter candidates using a given custom
     * {@link org.springframework.core.type.filter.TypeFilter} implementation.
     */
    CUSTOM

}

3、  JpaRepositoryFactoryBean

FactoryBean 是一个可以在 IOC而容器中被管理的一个 bean,  是对各种处理过程和资源使用的抽象,  FactoryBean 在需要

时产生另一个对象,而不返回 FactoryBean本身,   我们可以把它看成是一个抽象工厂,对它的调用返回的是工厂生产的产

品,  如对代理对象的处理,对事务性代理的处理等

public class JpaRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable> extends
        TransactionalRepositoryFactoryBeanSupport<T, S, ID> {

    private EntityManager entityManager;

    /**
     * The {@link EntityManager} to be used.
     * 
     * @param entityManager the entityManager to set
     */
    @PersistenceContext
    public void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }


    @Override
    public void setMappingContext(MappingContext<?, ?> mappingContext) {
        super.setMappingContext(mappingContext);
    }

/*
   * 看这里
   */
@Override
protected RepositoryFactorySupport doCreateRepositoryFactory() { return createRepositoryFactory(entityManager); } protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) { return new JpaRepositoryFactory(entityManager); } @Override public void afterPropertiesSet() { Assert.notNull(entityManager, "EntityManager must not be null!"); super.afterPropertiesSet(); } }

4、  JpaRepositoryFactory

    /*
     * Create a repository instance as backing for the query proxy.
   * 实例化自定义RepositoryImpl时,会注入EntityManager    
*/ @Override protected Object getTargetRepository(RepositoryInformation information) { SimpleJpaRepository<?, ?> repository = getTargetRepository(information, entityManager); repository.setRepositoryMethodMetadata(crudMethodMetadataPostProcessor.getCrudMethodMetadata()); return repository; } /** * Callback to create a {@link JpaRepository} instance with the given {@link EntityManager}
   *
*/ protected <T, ID extends Serializable> SimpleJpaRepository<?, ?> getTargetRepository(RepositoryInformation information, EntityManager entityManager) { JpaEntityInformation<?, Serializable> entityInformation = getEntityInformation(information.getDomainType()); return getTargetRepositoryViaReflection(information, entityInformation, entityManager); } /** * Returns the base class backing the actual repository instance. Make sure * {@link #getTargetRepository(RepositoryMetadata)} returns an instance of this class. */ @Override protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) { if (isQueryDslExecutor(metadata.getRepositoryInterface())) { return QueryDslJpaRepository.class; } else { return SimpleJpaRepository.class; } }

5、 自定义的RepositoryImpl时,注入自身项目的SessionContext(或者是其他依赖), 如何处理

其实Repository不应该注入SessionContext

解答:

重写JpaRepositoryFactory 的 getTargetRepository(RepositoryInformation information)方法

public class BaseRepositoryFactoryBean<R extends JpaRepository<T, ID>, T, ID extends Serializable> extends JpaRepositoryFactoryBean<R, T, ID> {

    @Autowired
    private ISessionContext sessionContext;

    @Override
    protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {

        return new BaseRepositoryFactory(entityManager);
    }

    private class BaseRepositoryFactory<T extends BaseEntity, I extends Serializable>
            extends JpaRepositoryFactory {

        private final EntityManager entityManager;

        public BaseRepositoryFactory(EntityManager entityManager) {
            super(entityManager);
            this.entityManager = entityManager;
        }

        @Override
        protected Object getTargetRepository(RepositoryInformation information) {
            Class<T> clazz = (Class<T>) information.getDomainType();
            JpaEntityInformation<T, ID> entityInformation = getEntityInformation(clazz);
            return new BaseRepositoryImpl<>(entityInformation, entityManager, sessionContext);
        }

        @Override
        protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
            return BaseRepositoryImpl.class;
        }
    }

}
原文地址:https://www.cnblogs.com/yuyutianxia/p/8185033.html