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; } } }