Spring学习笔记: Repository实现(一)
来源:互联网 发布:c语言多进程编程实例 编辑:程序博客网 时间:2024/06/16 06:03
在使用Spring的过程中, 可以定义自己的Repository接口,并不需要完成具体的实现,Spring会帮助创建具体的实例.
如下面这样的对Mongo进行Query的Repository:
@Repositorypublic interface UserRepository extends MongoRepository<User, String> { Optional<User> findOneByActivationKey(String activationKey); List<User> findAllByActivatedIsFalseAndCreatedDateBefore(Instant dateTime); Optional<User> findOneByResetKey(String resetKey); Optional<User> findOneByEmail(String email); Optional<User> findOneByLogin(String login); Page<User> findAllByLoginNot(Pageable pageable, String login);}
问题来了,方法名应该遵循什么样的规则,Spring才能帮助实现呢。通过对Spring源码的分析,找到了对应的规则。
下面的例子是基于对Mongo的分析,Sql的基本类似,而且规则也是一样的。
源码库:spring-data-mongodb, spring-data-commons;
从MongoRepositoryFactory.java开始,这个Factory会去创建Repository的实例:
public class MongoRepositoryFactory extends RepositoryFactorySupport {}public abstract class RepositoryFactorySupport implements BeanClassLoaderAware, BeanFactoryAware { public <T> T getRepository(Class<T> repositoryInterface) { return getRepository(repositoryInterface, null); } public <T> T getRepository(Class<T> repositoryInterface, Object customImplementation) { ... // Create proxy ProxyFactory result = new ProxyFactory(); result.setTarget(target); result.setInterfaces(new Class[] { repositoryInterface, Repository.class }); ... result.addAdvice(new QueryExecutorMethodInterceptor(information, customImplementation, target)); ... }}
这里用ProxyFacotry实例,且添加了一个QueryExecutorMethodInterceptor. Proxy和MethodInterceptor,熟悉Javassist的都知道对应的用途, SpringAOP也有类似的实现,这里不赘述。
下面看QueryExecutorMethodInterceptor实现:
public class QueryExecutorMethodInterceptor implements MethodInterceptor { public QueryExecutorMethodInterceptor(RepositoryInformation repositoryInformation, Object customImplementation, Object target) { ... QueryLookupStrategy lookupStrategy = getQueryLookupStrategy(queryLookupStrategyKey, RepositoryFactorySupport.this.evaluationContextProvider); ... SpelAwareProxyProjectionFactory factory = new SpelAwareProxyProjectionFactory(); ... }}
SpelAwareProxyProjectionFactory 以后再研究。 现在主要看一下QueryLookupStrategy的实现MongoQueryLookupStrategy。
private static class MongoQueryLookupStrategy implements QueryLookupStrategy { @Override public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, ProjectionFactory factory, NamedQueries namedQueries) { MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, factory, mappingContext); String namedQueryName = queryMethod.getNamedQueryName(); if (namedQueries.hasQuery(namedQueryName)) { String namedQuery = namedQueries.getQuery(namedQueryName); return new StringBasedMongoQuery(namedQuery, queryMethod, operations, EXPRESSION_PARSER, evaluationContextProvider); } else if (queryMethod.hasAnnotatedQuery()) { return new StringBasedMongoQuery(queryMethod, operations, EXPRESSION_PARSER, evaluationContextProvider); } else { return new PartTreeMongoQuery(queryMethod, operations); } } }
如果没有用注解或xml定义query. 则会创建一个PartTreeMongoQuery实例。
public PartTreeMongoQuery(MongoQueryMethod method, MongoOperations mongoOperations) { super(method, mongoOperations); this.processor = method.getResultProcessor(); this.tree = new PartTree(method.getName(), processor.getReturnedType().getDomainType()); this.isGeoNearQuery = method.isGeoNearQuery(); this.context = mongoOperations.getConverter().getMappingContext(); }
解析创建的Repository里的方法主要是由PartTree来处理的。
PartTree里将方法分割成Subject和Predicate。以“By”为分割。
Subject源码列出来支持的操作,如”find|read|get|query|stream”, “count”,”exists”,”delete|remove”等。
而Predicate里则将字符用“Or”分割成OrPart, 而OrPart则用”And”分割成Part,Part源代码里列出了可用的关键词:
public static enum Type { BETWEEN(2, "IsBetween", "Between"), IS_NOT_NULL(0, "IsNotNull", "NotNull"), IS_NULL(0, "IsNull", "Null"), LESS_THAN( "IsLessThan", "LessThan"), LESS_THAN_EQUAL("IsLessThanEqual", "LessThanEqual"), GREATER_THAN("IsGreaterThan", "GreaterThan"), GREATER_THAN_EQUAL("IsGreaterThanEqual", "GreaterThanEqual"), BEFORE("IsBefore", "Before"), AFTER( "IsAfter", "After"), NOT_LIKE("IsNotLike", "NotLike"), LIKE("IsLike", "Like"), STARTING_WITH("IsStartingWith", "StartingWith", "StartsWith"), ENDING_WITH("IsEndingWith", "EndingWith", "EndsWith"), NOT_CONTAINING( "IsNotContaining", "NotContaining", "NotContains"), CONTAINING("IsContaining", "Containing", "Contains"), NOT_IN( "IsNotIn", "NotIn"), IN("IsIn", "In"), NEAR("IsNear", "Near"), WITHIN("IsWithin", "Within"), REGEX( "MatchesRegex", "Matches", "Regex"), EXISTS(0, "Exists"), TRUE(0, "IsTrue", "True"), FALSE(0, "IsFalse", "False"), NEGATING_SIMPLE_PROPERTY("IsNot", "Not"), SIMPLE_PROPERTY("Is", "Equals");...}
- Spring学习笔记: Repository实现(一)
- Spring学习笔记(一):Spring注解@Component、@Repository、@Service、@Controller区别
- Spring学习笔记(一)
- Spring 学习笔记(一)
- spring学习笔记(一)
- Spring学习笔记(一)
- Spring学习笔记(一)
- spring学习笔记(一)
- Spring 学习笔记(一)
- spring学习笔记(一)
- Spring 学习笔记(一)
- Spring学习笔记(一)
- Spring学习笔记(一)
- spring学习笔记(一)
- Spring学习笔记(一)
- spring学习笔记(一)
- Spring学习笔记(一)
- Spring 学习笔记(一)
- 常用的JQuery单击操作汇总
- hdu 1162 Eddy's picture 基础最小生成树★
- JS函数(一)
- 347. Top K Frequent Elements [leetcode]
- 如何提取mathematica方程的解,并用在后面的计算中
- Spring学习笔记: Repository实现(一)
- pip安装报错:is not a supported wheel on this platform
- 关于spring配置文件<context:property-placeholder>
- tocker笔记
- 双向 LSTM
- 剑指offer--二叉树的深度--层次遍历/BFS
- Centos 6 L*2tp 配置实例
- 使用Netty实现自定义推送
- 关于 Java 的10个谎言