博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
MongoRepository动态代理及jpa方法解析源码分析
阅读量:5160 次
发布时间:2019-06-13

本文共 18020 字,大约阅读时间需要 60 分钟。

public interface FzkRepository extends MongoRepository
{ Fzk findByName(String name);}
@RestController public class TestController {    @Autowired    private FzkRepository fzkReposiroty;}

为什么一个接口,没有实现类就能被注入?

首先如果想使用MongoRepository,一定会在配置中加入@EnableMongoRepositories,就从EnableMongoRepositories开始

@Import(MongoRepositoriesRegistrar.class)

跟踪进入RepositoryBeanDefinitionRegistrarSupport

public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry) {....        AnnotationRepositoryConfigurationSource configurationSource = new AnnotationRepositoryConfigurationSource(annotationMetadata, getAnnotation(), resourceLoader, environment, registry);

      if (annotationMetadata.getAnnotationAttributes(getAnnotation().getName()) == null) {

        return;
      }

RepositoryConfigurationExtension extension = getExtension();        RepositoryConfigurationUtils.exposeRegistration(extension, registry, configurationSource);        RepositoryConfigurationDelegate delegate = new RepositoryConfigurationDelegate(configurationSource, resourceLoader,                environment);        delegate.registerRepositoriesIn(registry, extension);    }

没什么可说的,只有使用了EnableMongoRepositories才会继续进行,注册bean交给了RepositoryConfigurationDelegate 来进行。继续进入RepositoryConfigurationDelegate.registerRepositoriesIn方法

1 public List<BeanComponentDefinition> registerRepositoriesIn(BeanDefinitionRegistry registry, 2 RepositoryConfigurationExtension extension) { 3 4 extension.registerBeansForRoot(registry, configurationSource); 5 6 RepositoryBeanDefinitionBuilder builder = new RepositoryBeanDefinitionBuilder(registry, extension, resourceLoader, 7 environment); 8 List<BeanComponentDefinition> definitions = new ArrayList<BeanComponentDefinition>(); 9 10 for (RepositoryConfiguration<? extends RepositoryConfigurationSource> configuration : extension 11 .getRepositoryConfigurations(configurationSource, resourceLoader, inMultiStoreMode)) { 12 13 BeanDefinitionBuilder definitionBuilder = builder.build(configuration); 14 15 extension.postProcess(definitionBuilder, configurationSource); 16 17 if (isXml) { 18 extension.postProcess(definitionBuilder, (XmlRepositoryConfigurationSource) configurationSource); 19 } else { 20 extension.postProcess(definitionBuilder, (AnnotationRepositoryConfigurationSource) configurationSource); 21 } 22 23 AbstractBeanDefinition beanDefinition = definitionBuilder.getBeanDefinition(); 24 String beanName = beanNameGenerator.generateBeanName(beanDefinition, registry); 25 26 if (LOGGER.isDebugEnabled()) { 27 LOGGER.debug(REPOSITORY_REGISTRATION, extension.getModuleName(), beanName, 28 configuration.getRepositoryInterface(), extension.getRepositoryFactoryClassName()); 29 } 30 31 beanDefinition.setAttribute(FACTORY_BEAN_OBJECT_TYPE, configuration.getRepositoryInterface()); 32 33 registry.registerBeanDefinition(beanName, beanDefinition); 34 definitions.add(new BeanComponentDefinition(beanDefinition, beanName)); 35 } 36 37 return definitions; 38 }

扫描实现了MongoRepository的接口并生成RepositoryConfigurationSource的逻辑在RepositoryConfigurationExtensionSupport.getRepositoryConfigurations方法中

public 
Collection
> getRepositoryConfigurations( T configSource, ResourceLoader loader, boolean strictMatchesOnly) {.... Set
> result = new HashSet
>(); for (BeanDefinition candidate : configSource.getCandidates(loader)) { RepositoryConfiguration
configuration = getRepositoryConfiguration(candidate, configSource); if (!strictMatchesOnly || configSource.usesExplicitFilters()) { result.add(configuration); continue; } Class
repositoryInterface = loadRepositoryInterface(configuration, loader); if (repositoryInterface == null || isStrictRepositoryCandidate(repositoryInterface)) { result.add(configuration); } } return result; }

继续跟踪RepositoryConfigurationSourceSupport.getCandidates

public Collection
getCandidates(ResourceLoader loader) { RepositoryComponentProvider scanner = new RepositoryComponentProvider(getIncludeFilters(), registry); scanner.setConsiderNestedRepositoryInterfaces(shouldConsiderNestedRepositories()); scanner.setEnvironment(environment); scanner.setResourceLoader(loader); for (TypeFilter filter : getExcludeFilters()) { scanner.addExcludeFilter(filter); } Set
result = new HashSet
(); for (String basePackage : getBasePackages()) { Set
candidate = scanner.findCandidateComponents(basePackage); result.addAll(candidate); } return result; }

RepositoryComponentProvider.findCandidateComponents,先由父类ClassPathScanningCandidateComponentProvider处理

public Set
findCandidateComponents(String basePackage) { Set
candidates = new LinkedHashSet
(); String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + (basePackage) + '/' + this.resourcePattern; Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath); ......for (Resource resource : resources) { ...... MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource); if (isCandidateComponent(metadataReader)) { ...... }
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {        for (TypeFilter tf : this.excludeFilters) {  //1            if (tf.match(metadataReader, this.metadataReaderFactory)) {                return false;            }        }        for (TypeFilter tf : this.includeFilters) {  //2            if (tf.match(metadataReader, this.metadataReaderFactory)) { return isConditionMatch(metadataReader); } } return false; }

  private boolean isConditionMatch(MetadataReader metadataReader) {

    if (this.conditionEvaluator == null) {
      this.conditionEvaluator = new ConditionEvaluator(getRegistry(), getEnvironment(), getResourceLoader());
    }
    return !this.conditionEvaluator.shouldSkip(metadataReader.getAnnotationMetadata());
  }

 

判断条件,1.如果是注解了NoRepositoryBean就不处理,2.判断了是Repository后,继续判断是否有@Condition。找到了所有复合条件的类后,组成RepositoryConfiguration后,继续跟踪RepositoryConfigurationDelegate.registerRepositoriesIn,组成BeanDefinitionBuilder,构件出MongoRepositoryFactoryBean。

public class MongoRepositoryFactoryBean
, S, ID extends Serializable> extends RepositoryFactoryBeanSupport
public abstract class RepositoryFactoryBeanSupport
, S, ID extends Serializable> implements InitializingBean, RepositoryFactoryInformation
, FactoryBean
, BeanClassLoaderAware, BeanFactoryAware, ApplicationEventPublisherAware

MongoRepositoryFactoryBean间接实现InitializingBean,因此他会实现afterPropertiesSet方法

在AbstractApplicationContext  ->  refresh()   ->   finishBeanFactoryInitialization()阶段,实例化bean时进行实例化。

这个例子里,TestController注入了FzkRepository ,实例化TestController时发现需要注入FzkRepository 会先实例化FzkRepository。
在DefaultListableBeanFactory的preInstantiateSingletons()时

public void preInstantiateSingletons() throws BeansException {......        for (String beanName : beanNames) {            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {                if (isFactoryBean(beanName)) {                    final FactoryBean
factory = (FactoryBean
) getBean(FACTORY_BEAN_PREFIX + beanName); boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged(new PrivilegedAction
() { @Override public Boolean run() { return ((SmartFactoryBean
) factory).isEagerInit(); } }, getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean
) factory).isEagerInit()); } if (isEagerInit) { getBean(beanName); } } else { getBean(beanName); } } } ...... }
protected 
T doGetBean( final String name, final Class
requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {...... // Create bean instance. if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory
() { @Override public Object getObject() throws BeansException { try { return createBean(beanName, mbd, args); } catch (BeansException ex) {...... } } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); }...... return (T) bean; }

多次调用进入AbstractAutowireCapableBeanFactory.doCreateBean。

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)            throws BeanCreationException {......        // Initialize the bean instance.        Object exposedObject = bean;        try {            populateBean(beanName, mbd, instanceWrapper);            if (exposedObject != null) {                exposedObject = initializeBean(beanName, exposedObject, mbd);            }        }......    }
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {......            invokeInitMethods(beanName, wrappedBean, mbd);......    }protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)            throws Throwable {......                ((InitializingBean) bean).afterPropertiesSet();......     }

上面说了由BeanDefinitionBuilder构件出MongoRepositoryFactoryBean,而MongoRepositoryFactoryBean实现了InitializingBean,这里进入到了MongoRepositoryFactoryBean.afterPropertiesSet

public void afterPropertiesSet() {        super.afterPropertiesSet();        Assert.notNull(operations, "MongoTemplate must not be null!");        if (!mappingContextConfigured) {            setMappingContext(operations.getConverter().getMappingContext());        }    }

进入到父累RepositoryFactoryBeanSupport.afterPropertiesSet

public void afterPropertiesSet() {        this.factory = createRepositoryFactory();......        if (publisher != null) {            this.factory.addRepositoryProxyPostProcessor(new EventPublishingRepositoryProxyPostProcessor(publisher));        }        this.repositoryMetadata = this.factory.getRepositoryMetadata(repositoryInterface);        if (!lazyInit) {            initAndReturn();        }    }    private T initAndReturn() {......        if (this.repository == null) {            this.repository = this.factory.getRepository(repositoryInterface, customImplementation);        }        return this.repository;    }

这里的factory是MongoRepositoryFactory,接下来,才是创建代理的部分

public 
T getRepository(Class
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, projectionFactory)); return (T) result.getProxy(classLoader); }

第一重点是ProxyFactory,这里target是SimpleMongoRepository,repositoryInterface是FzkRepository(自己的接口)。

另一个重点是增加了一个切入点QueryExecutorMethodInterceptor。看看QueryExecutorMethodInterceptor

public QueryExecutorMethodInterceptor(RepositoryInformation repositoryInformation, Object customImplementation,                Object target, ProjectionFactory projectionFactory) {......            this.resultHandler = new QueryExecutionResultHandler();            this.repositoryInformation = repositoryInformation;            this.customImplementation = customImplementation;            this.target = target;            QueryLookupStrategy lookupStrategy = getQueryLookupStrategy(queryLookupStrategyKey,                    RepositoryFactorySupport.this.evaluationContextProvider);            lookupStrategy = lookupStrategy == null ? getQueryLookupStrategy(queryLookupStrategyKey) : lookupStrategy;            Iterable
queryMethods = repositoryInformation.getQueryMethods();...... for (Method method : queryMethods) { RepositoryQuery query = lookupStrategy.resolveQuery(method, repositoryInformation, projectionFactory, namedQueries); invokeListeners(query); queries.put(method, query); } }

首先他是一个MethodInterceptor,一个有个invoke方法,这个方法之后在说。现在先看构造器里干了什么。

首先构件一个MongoRepositoryFactory$MongoQueryLookupStrategy类型的lookupStrategy 。处理jpa写法的方法就是由它来处理,这里的例子是findByName方法。继续跟踪,看看是怎么将findByName解析成{"name" : ***}的。写了这么多,终于快到终点了。继续看,进入到MongoQueryLookupStrategy.resolveQuery

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

这里,无@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();    }public class PartTree {    private static final String KEYWORD_TEMPLATE = "(%s)(?=(\\p{Lu}|\\P{InBASIC_LATIN}))";    private static final String QUERY_PATTERN = "find|read|get|query|stream";    private static final String COUNT_PATTERN = "count";    private static final String EXISTS_PATTERN = "exists";    private static final String DELETE_PATTERN = "delete|remove";    private static final Pattern PREFIX_TEMPLATE = Pattern.compile( //            "^(" + QUERY_PATTERN + "|" + COUNT_PATTERN + "|" + EXISTS_PATTERN + "|" + DELETE_PATTERN + ")((\\p{Lu}.*?))??By");    public PartTree(String source, Class
domainClass) {...... Matcher matcher = PREFIX_TEMPLATE.matcher(source); if (!matcher.find()) { this.subject = new Subject(null); this.predicate = new Predicate(source, domainClass); } else { this.subject = new Subject(matcher.group(0)); this.predicate = new Predicate(source.substring(matcher.group().length()), domainClass); } }}

最终生成的query,已经将name(key)解析出来了。

至此,终于解析完,怎么创建的代理,怎么根据方法名来解析sql。最后就是使用点

上面说了,使用时,会调用QueryExecutorMethodInterceptor.invoke

public Object invoke(MethodInvocation invocation) throws Throwable {            Object result = doInvoke(invocation);            return resultHandler.postProcessInvocationResult(result, invocation.getMethod());        }        private Object doInvoke(MethodInvocation invocation) throws Throwable {            Method method = invocation.getMethod();            Object[] arguments = invocation.getArguments();            if (isCustomMethodInvocation(invocation)) {                Method actualMethod = repositoryInformation.getTargetClassMethod(method);                return executeMethodOn(customImplementation, actualMethod, arguments);            }            if (hasQueryFor(method)) {                return queries.get(method).execute(arguments);            }            // Lookup actual method as it might be redeclared in the interface            // and we have to use the repository instance nevertheless            Method actualMethod = repositoryInformation.getTargetClassMethod(method);            return executeMethodOn(target, actualMethod, arguments);        }

queries.get(method)得到PartTreeMongoQuery

public Object execute(Object[] parameters) {        MongoParameterAccessor accessor = new MongoParametersParameterAccessor(method, parameters);        Query query = createQuery(new ConvertingParameterAccessor(operations.getConverter(), accessor));        applyQueryMetaAttributesWhenPresent(query);        ResultProcessor processor = method.getResultProcessor().withDynamicProjection(accessor);        String collection = method.getEntityInformation().getCollectionName();        MongoQueryExecution execution = getExecution(query, accessor,                new ResultProcessingConverter(processor, operations, instantiators));        return execution.execute(query, processor.getReturnedType().getDomainType(), collection);    }

构件出Query得到结果返回

转载于:https://www.cnblogs.com/badboyf/p/10252694.html

你可能感兴趣的文章
面试时被问到的问题
查看>>
注解小结
查看>>
201421410014蒋佳奇
查看>>
Xcode5和ObjC新特性
查看>>
CSS属性值currentColor
查看>>
Real-Time Rendering 笔记
查看>>
多路复用
查看>>
spring IOC装配Bean(注解方式)
查看>>
处理程序“PageHandlerFactory-Integrated”在其模块列表中有一个错误模块“Manag
查看>>
利用SignalR来同步更新Winfrom
查看>>
反射机制
查看>>
CocoaPod
查看>>
BZOJ 1251: 序列终结者 [splay]
查看>>
5G边缘网络虚拟化的利器:vCPE和SD-WAN
查看>>
MATLAB基础入门笔记
查看>>
【UVA】434-Matty&#39;s Blocks
查看>>
Android开发技术周报 Issue#80
查看>>
hadoop2.2.0+hive-0.10.0完全分布式安装方法
查看>>
django知识点总结
查看>>
C++ STL stack、queue和vector的使用
查看>>