SpringDataJpa中,直接按照命名规范命名就能查询的实现原理

文章详细描述了如何通过JpaRepositoryFactoryBean创建Repository的代理对象,涉及代理的后置处理器、Repository基类、命名查询和查询方法的执行拦截。重点介绍了查询方法查找策略和如何处理不同类型的查询,如@Query注解、命名查询和默认方法拦截。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

// JpaRepositoryFactoryBean创建Repository的getObject就是通过JpaRepositoryFactory.getRepository获取
class JpaRepositoryFactory {
    // 创建代理的后置处理器,就是给要给代理添加拦截器
    private final List<RepositoryProxyPostProcessor> postProcessors;
    // Repository的基类
    private Optional<Class<?>> repositoryBaseClass;
    // 命名查询器
    private NamedQueries namedQueries = new PropertiesBasedNamedQueries(new Properties());

    public JpaRepositoryFactory(EntityManager entityManager) {
        // 实体管理器
        this.entityManager = entityManager;
        // 查询的提取器的提供商,不同提供商的提取方式不一样,,可能是Hibernate persistence provider,EclipseLink persistence provider,Use standard JPA
        this.extractor = PersistenceProvider.fromEntityManager(entityManager);
        // crud方法的元数据后置处理器
        this.crudMethodMetadataPostProcessor = new CrudMethodMetadataPostProcessor();
        // 实体路径解析器
        this.entityPathResolver = SimpleEntityPathResolver.INSTANCE;
        // 添加RepositoryProxy代理的后置处理器
        addRepositoryProxyPostProcessor(crudMethodMetadataPostProcessor);
        // 添加RepositoryProxy代理的后置处理器
        addRepositoryProxyPostProcessor((factory, repositoryInformation) -> {
            // 如果有Repository中的方法,返回Stream,则需要添加一个代理方法拦截器
            // SurroundingTransactionDetectorMethodInterceptor,它是一个枚举
            if (hasMethodReturningStream(repositoryInformation.getRepositoryInterface())) {
                SurroundingTransactionDetectorMethodInterceptor advice = SurroundingTransactionDetectorMethodInterceptor.INSTANCE
                {
                    private final ThreadLocal<Boolean> SURROUNDING_TX_ACTIVE = new ThreadLocal<>();
                    // 保存当前线程是否真实获取到事务信息标记
                    SURROUNDING_TX_ACTIVE.set(TransactionSynchronizationManager.isActualTransactionActive());
                    // 放行
                    Object res = invocation.proceed();
                    // 删除标记
                    SURROUNDING_TX_ACTIVE.remove();
                    return res;
                }
                // 添加拦截器
                factory.addAdvice(advice);
            }
        });
        // 如果持久化机制的提供商是EclipseLink
        if (extractor.equals(PersistenceProvider.ECLIPSELINK)) {
            // 添加查询创建监听器
            addQueryCreationListener(new EclipseLinkProjectionQueryCreationListener(entityManager));
        }
    }

    // 获取Repository的实现
    public <T> T getRepository(Class<T> repositoryInterface, RepositoryFragments fragments) {
        // 获取Repository接口的元数据信息
        RepositoryMetadata metadata = getRepositoryMetadata(repositoryInterface);
        // 将所有碎片接口进行组合,返回一个Repository组合类
        RepositoryComposition composition = getRepositoryComposition(metadata, fragments);
        // 获取Repository接口信息
        RepositoryInformation information = getRepositoryInformation(metadata, composition);
        // 校验接口是否存在实现类
        validate(information, composition);
        // 生成Repository实现类
        Object target = getTargetRepository(information);
        // 准备给Repository创建代理对象
        ProxyFactory result = new ProxyFactory();
        // 设置目标类
        result.setTarget(target);
        // 设置需要实现的接口
        result.setInterfaces(repositoryInterface, Repository.class, TransactionalProxy.class);
        // 如果支持拦截该接口,添加一个拦截器
        if (MethodInvocationValidator.supports(repositoryInterface)) {
            result.addAdvice(new MethodInvocationValidator());
        }
        // 添加一个切面它只负责保存当前正在执行的MethodInvocation对象
        result.addAdvisor(ExposeInvocationInterceptor.ADVISOR);
        // 执行所有的后置处理器
        /**
         * {@link TransactionalRepositoryProxyPostProcessor#postProcess(ProxyFactory, RepositoryInformation)}
         * {@link JpaRepositoryFactory(EntityManager entityManager)}
         */
        postProcessors.forEach(processor -> processor.postProcess(result, information));
        // 该接口是否存在默认方法,如果存在,需要添加拦截器
        if (DefaultMethodInvokingMethodInterceptor.hasDefaultMethods(repositoryInterface)) {
            // 添加默认方法拦截器
            result.addAdvice(new DefaultMethodInvokingMethodInterceptor());
        }
        // 创建映射信息
        ProjectionFactory projectionFactory = getProjectionFactory(classLoader, beanFactory);
        // 添加查询方法执行拦截器,包含命名查询,普通查询等等
        result.addAdvice(new QueryExecutorMethodInterceptor(information, projectionFactory));
        // 将当前接口自动生成的实现类也进行组合
        composition = composition.append(RepositoryFragment.implemented(target));
        // 添加实现类方法执行器的拦截器
        result.addAdvice(new ImplementationMethodExecutionInterceptor(composition));
        // 获取Repository接口实现类的代理对象
        T repository = (T) result.getProxy(classLoader);
        // 返回代理对象
        return repository;
    }
}
// 查询方法执行拦截器,包含命名查询,普通查询,以及按照jpa命名规范都在这里完成的
class QueryExecutorMethodInterceptor {
    public QueryExecutorMethodInterceptor(RepositoryInformation repositoryInformation, ProjectionFactory projectionFactory) {
        // 结果查询的处理器,使用类型转换器对返回结果进行转换
        this.resultHandler = new QueryExecutionResultHandler(CONVERSION_SERVICE);
        // 创建一个查询方法的策略
        Optional<QueryLookupStrategy> lookupStrategy = getQueryLookupStrategy(queryLookupStrategyKey, RepositoryFactorySupport.this.evaluationContextProvider);
        // 如果不存在查找策略,但是存在查询方法,抛出异常
        if (!lookupStrategy.isPresent() && repositoryInformation.hasQueryMethods()) {
            throw new IllegalStateException("You have defined query method in the repository but");
        }
        // 使用查找策略查找查询方法,将方法对应映射成RepositoryQuery可执行的query对象
        this.queries = lookupStrategy.map(it -> mapMethodsToQuery(repositoryInformation, it, projectionFactory)).orElse(Collections.emptyMap());
    }

    // 根据标注@EnableJpaRepositories的queryLookupStrategy方法查询方法查找策略
    // 根据不同的策略处理目标方法
    protected Optional<QueryLookupStrategy> getQueryLookupStrategy(@Nullable Key key, QueryMethodEvaluationContextProvider evaluationContextProvider) {
        return Optional.of(JpaQueryLookupStrategy.create(entityManager, key, extractor, evaluationContextProvider, escapeCharacter)
        {
            // 默认策略为,如果方法不存在,则创建查询
            switch (key != null ? key : Key.CREATE_IF_NOT_FOUND) {
                // 直接创建查询
                case CREATE:
                    return new CreateQueryLookupStrategy(em, extractor, escape);
                // 使用@Query注解创建查询
                case USE_DECLARED_QUERY:
                    return new DeclaredQueryLookupStrategy(em, extractor, evaluationContextProvider);
                // 上面两者的兼容版本,先使用@Query注解查找,如果不存在,在使用方法名创建
                case CREATE_IF_NOT_FOUND:
                    return new CreateIfNotFoundQueryLookupStrategy(em, extractor,
                            new CreateQueryLookupStrategy(em, extractor, escape),
                            new DeclaredQueryLookupStrategy(em, extractor, evaluationContextProvider));
                default:
                    throw new IllegalArgumentException(String.format("Unsupported query lookup strategy %s!", key));
            }
        });
    }

    // 将方法映射成RepositoryQuery对象
    private Map<Method, RepositoryQuery> mapMethodsToQuery(RepositoryInformation repositoryInformation, QueryLookupStrategy lookupStrategy, ProjectionFactory projectionFactory) {
        /**
         * {@link DefaultRepositoryInformation#getQueryMethods()}
         */
        // 获取找的的查询方法
        return repositoryInformation.getQueryMethods().stream()
                // 解析查询方法中的查询注解,参数,查询等信息
                // 封装成可执行的Query对象
                .map(method -> lookupQuery(method, repositoryInformation, lookupStrategy, projectionFactory)) //
                // 执行监听器
                .peek(pair -> invokeListeners(pair.getSecond())) //
                .collect(Pair.toMap());
    }

    // 查找查询方法的信息
    private Pair<Method, RepositoryQuery> lookupQuery(Method method, RepositoryInformation information, QueryLookupStrategy strategy, ProjectionFactory projectionFactory) {
        /**
         * {@link JpaQueryLookupStrategy}
         */
        // 使用查询策略,解析查询方法,将查询的信息封装为可执行的Query方法
        return Pair.of(method, strategy.resolveQuery(method, information, projectionFactory, namedQueries));
    }

    // 查询查询创建监听器
    private void invokeListeners(RepositoryQuery query) {
        // 在构造方法中
        // 	QueryCollectingQueryCreationListener collectingListener = new QueryCollectingQueryCreationListener();
        //  this.queryPostProcessors.add(collectingListener);
        class QueryCollectingQueryCreationListener implements QueryCreationListener<RepositoryQuery> {
            private final List<QueryMethod> queryMethods = new ArrayList<>();

            // 创建的回调方法
            public void onCreation(RepositoryQuery query) {
                // 保存query中可执行的方法
                this.queryMethods.add(query.getQueryMethod());
            }
        }
        // 执行QueryCollectingQueryCreationListener监听器,在创建了方法对应的Query对象之后执行对应回调
        for (QueryCreationListener listener : queryPostProcessors) {
            // 解析该类的泛型信息,也就是RepositoryQuery
            ResolvableType typeArgument = ResolvableType.forClass(QueryCreationListener.class, listener.getClass()).getGeneric(0);
            // 如果解析到了泛型类
            if (typeArgument != null && typeArgument.isAssignableFrom(ResolvableType.forClass(query.getClass()))) {
                // 回调监听器的创建方法
                /**
                 * {@link QueryCollectingQueryCreationListener#onCreation(RepositoryQuery)}
                 */
                listener.onCreation(query);
            }
        }
    }

    // 拦截方法
    public Object invoke(@SuppressWarnings("null") MethodInvocation invocation) throws Throwable {
        // 获取需要执行的方法
        Method method = invocation.getMethod();
        // 获取查询执行器的是适配器
        QueryExecutionConverters.ExecutionAdapter executionAdapter = QueryExecutionConverters.getExecutionAdapter(method.getReturnType());
        // 不存在适配器
        if (executionAdapter == null) {
            // 执行目标方法
            Object res = doInvoke(invocation){
                // 获取方法
                Method method = invocation.getMethod();
                // 如果命名查询中包含此方法
                if (hasQueryFor(method){
                    return queries.containsKey(method);
                }) {
                    // 获取到可执行的Query对象执行目标方法
                    return queries.get(method).execute(invocation.getArguments());
                }
                // 放行
                return invocation.proceed();
            }
            // 处理结果,类型转换,给集合默认值等等
            return resultHandler.postProcessInvocationResult(res, method);
        }
        return executionAdapter.apply(() -> resultHandler.postProcessInvocationResult(doInvoke(invocation), method));
    }
}

// JPA查询方法的查找策略
public class JpaQueryLookupStrategy {
    // 抽象的查询策略
    private abstract static class AbstractQueryLookupStrategy implements QueryLookupStrategy {
        // 实体管理器
        private final EntityManager em;
        // 查询提取器,不同的厂商实现提取方式不一样
        private final QueryExtractor provider;

        public AbstractQueryLookupStrategy(EntityManager em, QueryExtractor extractor) {
            this.em = em;
            this.provider = extractor;
        }

        // 解析查询方法
        public final RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, ProjectionFactory factory, NamedQueries namedQueries) {
            // 解析查询方法,将参数封装成JpaQueryMethod
            return resolveQuery(new JpaQueryMethod(method, metadata, factory, provider), em, namedQueries);
        }

        protected abstract RepositoryQuery resolveQuery(JpaQueryMethod method, EntityManager em, NamedQueries namedQueries);
    }

    // 查找@Query注解的策略
    private static class DeclaredQueryLookupStrategy extends AbstractQueryLookupStrategy {
        // 负责提供查询方法的上下文信息,以便框架能够正确地解析和执行这些查询方法
        private final QueryMethodEvaluationContextProvider evaluationContextProvider;

        public DeclaredQueryLookupStrategy(EntityManager em, QueryExtractor extractor, QueryMethodEvaluationContextProvider evaluationContextProvider) {
            super(em, extractor);
            this.evaluationContextProvider = evaluationContextProvider;
        }

        // 解析查询语句
        protected RepositoryQuery resolveQuery(JpaQueryMethod method, EntityManager em, NamedQueries namedQueries) {
            // 解析Query注解,返回可执行的Query类
            RepositoryQuery query = JpaQueryFactory.INSTANCE.fromQueryAnnotation(method, em, evaluationContextProvider)
            {
                // 通过Query中的SQL进行解析
                return fromMethodWithQueryString(method, em, method.getAnnotatedQuery() {
                // 查询Query注解的value值SQL
                return getMergedOrDefaultAnnotationValue(attribute, Query.class, type);
            },evaluationContextProvider){
                if (queryString == null) {
                    return null;
                }
                // 如果是SQL查询,创建一个SQL的执行器
                return method.isNativeQuery() ? new NativeJpaQuery(method, em, queryString, evaluationContextProvider, PARSER)
                        // 否则,使用默认的JPA查询器
                        : new SimpleJpaQuery(method, em, queryString, evaluationContextProvider, PARSER);
            }
            }
            // 如果存在Query注解,直接返回
            if (null != query) {
                return query;
            }
            // 找存储过程@Procedure注解
            query = JpaQueryFactory.INSTANCE.fromProcedureAnnotation(method, em) {
                // 如果不存在@Procedure注解,直接返回
                if (!method.isProcedureQuery()) {
                    return null;
                }
                // 返回存储过程的查询类
                return new StoredProcedureJpaQuery(method, em);
            }
            // 如果存在@Procedure注解,直接返回
            if (null != query) {
                return query;
            }
            // 其他情况,@Query中不存在SQL语句
            String name = method.getNamedQueryName() {
                // 先获取Query注解的名称
                String annotatedName = getAnnotationValue("name", String.class);
                // 没有写name属性,返回类名.方法名
                return StringUtils.hasText(annotatedName) ? annotatedName : super.getNamedQueryName() {
                    return String.format("%s.%s", getDomainClass().getSimpleName(), method.getName());
                }
            }
            // 如果命名查询中已经定义了该方法
            if (namedQueries.hasQuery(name)) {
                // 获取对应的查询语句
                String queryString = namedQueries.getQuery(name);
                // 上面有解释,又到了@Query的环节,上面找的是@Query的SQL,现在找的是@Query的name,然后在通过name到命名查询(jpa-named-queries.properties配置文件)中找到对应的SQL
                return JpaQueryFactory.INSTANCE.fromMethodWithQueryString(method, em, queryString, evaluationContextProvider);

            }
            // 如果命名查询中也不存在该方法
            query = NamedQuery.lookupFrom(method, em) {
                // 获取到查询名称,上面也有解释
                // 先获取Query注解的名称
                // 没有写name属性,返回类名.方法名
                final String queryName = method.getNamedQueryName();
                // 是否存在命名查询
                if (!hasNamedQuery(em, queryName) {
                    // 新建一个实体管理器
                    EntityManager lookupEm = em.getEntityManagerFactory().createEntityManager();
                    try {
                        // 尝试用EntityManager创建命名查询,只有在实体类中定义了命名查询才能通过,否则抛出异常
                        // @NamedQuery(name = "User.findUserByName", query = "select u FROM User u where u.name ='luck'")
                        // public class User {}
                        // 提示: 这种存在一种特殊情况,如果命名查询的名称正好符合默认的规则"类名.方法名"
                        // 那么,没有加@Query和加了@Query但没有设置name的作用是一样的
                        lookupEm.createNamedQuery(queryName);
                        return true;
                    } catch (IllegalArgumentException e) {
                        // 没有定义该命名查询
                        return false;
                    } finally {
                        // 关闭连接
                        lookupEm.close();
                    }

                }){
                    // 返回空,@Query注解的情况处理不了这个方法
                    return null;
                }
                // 如果在实体中定义了该命名查询,返回NamedQuery
                RepositoryQuery query = new NamedQuery(method, em);
                return query;
            }
            // 如果处理@Query情况成功,直接返回对应的可执行的Query对象
            if (null != query) {
                return query;
            }
            // 返回null,表示无法处理Query注解命名查询的逻辑,抛出异常
            throw new IllegalStateException(String.format("Did neither find a NamedQuery nor an annotated query for method %s!", method));
        }
    }

    // 根据方法命按照命名规则创建查询
    private static class CreateQueryLookupStrategy extends AbstractQueryLookupStrategy {

        // 负责提供查询方法的上下文信息,以便框架能够正确地解析和执行这些查询方法
        private final PersistenceProvider persistenceProvider;
        // 转义字符处理器
        private final EscapeCharacter escape;

        public CreateQueryLookupStrategy(EntityManager em, QueryExtractor extractor, EscapeCharacter escape) {
            super(em, extractor);
            this.persistenceProvider = PersistenceProvider.fromEntityManager(em);
            this.escape = escape;
        }

        // 创建一个Query对象,也就是按照SpringDataJpa的命名规则,解析方法名为树,提取字段和关键字
        protected RepositoryQuery resolveQuery(JpaQueryMethod method, EntityManager em, NamedQueries namedQueries) {
            return new PartTreeJpaQuery(method, em, persistenceProvider, escape) {

            }
        }
    }

    // 上面两种的兼容版本
    private static class CreateIfNotFoundQueryLookupStrategy extends AbstractQueryLookupStrategy {

        // 处理@Query注解的策略
        private final DeclaredQueryLookupStrategy lookupStrategy;
        // 直接创建名称树查询的策略
        private final CreateQueryLookupStrategy createStrategy;

        public CreateIfNotFoundQueryLookupStrategy(EntityManager em, QueryExtractor extractor, CreateQueryLookupStrategy createStrategy, DeclaredQueryLookupStrategy lookupStrategy) {
            super(em, extractor);
            this.createStrategy = createStrategy;
            this.lookupStrategy = lookupStrategy;
        }

        // 解析查询
        protected RepositoryQuery resolveQuery(JpaQueryMethod method, EntityManager em, NamedQueries namedQueries) {
            // 先处理@Query,如果处理不成功则创建
            try {
                return lookupStrategy.resolveQuery(method, em, namedQueries);
            } catch (IllegalStateException e) {
                return createStrategy.resolveQuery(method, em, namedQueries);
            }
        }
    }

}

// JPA命名规范解析树查询
class PartTreeJpaQuery {
    PartTreeJpaQuery(JpaQueryMethod method, EntityManager em, PersistenceProvider persistenceProvider, EscapeCharacter escape) {
        super(method, em);
        this.em = em;
        this.escape = escape;
        // 实体类型
        Class<?> domainClass = method.getEntityInformation().getJavaType();
        // 方法参数
        this.parameters = method.getParameters();
        // 可能是用于检查查询方法是否包含动态投影
        // 动态投影是指在查询中根据条件动态选择要返回的字段或属性
        // 或者特殊的参数分页或者排序
        boolean recreationRequired = parameters.hasDynamicProjection() || parameters.potentiallySortsDynamically();

        try {
            // 构建一个方法树
            this.tree = new PartTree(method.getName(), domainClass) {
                +
                String KEYWORD_TEMPLATE = "(%s)(?=(\\p{Lu}|\\P{InBASIC_LATIN}))";
                +
                String QUERY_PATTERN = "find|read|get|query|stream";
                +
                String COUNT_PATTERN = "count";
                +
                String EXISTS_PATTERN = "exists";
                +
                String DELETE_PATTERN = "delete|remove";
                +
                Pattern PREFIX_TEMPLATE = Pattern.compile("^(" + QUERY_PATTERN + "|" + COUNT_PATTERN + "|" + EXISTS_PATTERN + "|" + DELETE_PATTERN + ")((\\p{Lu}.*?))??By");
                // 主题,就是需要执行的最终操作,是查询,删除...操作
                private final Subject subject;
                // 运算到主题中的条件
                private final Predicate predicate;
                // 匹配上面的关键字
                Matcher matcher = PREFIX_TEMPLATE.matcher(source);
                // 如果方法名没有匹配到
                if(!matcher.find())

                {
                    // 指定空主题
                    this.subject = new Subject(Optional.empty());
                    // 方法名作为条件
                    this.predicate = new Predicate(source, domainClass);
                }
                // 方法名匹配到了关键字
                else

                {
                    // 使用匹配到的第一处关键字作为主题
                    this.subject = new Subject(Optional.of(matcher.group(0))) {
                        // 主题为去查
                        this.distinct =subject.map(it ->it.contains(DISTINCT)).

                        orElse(false);
                        // 主题为查询数量
                        this.count =

                        matches(subject, COUNT_BY_TEMPLATE);
                        // 是否存在
                        this.exists =

                        matches(subject, EXISTS_BY_TEMPLATE);
                        // 删除
                        this.delete =

                        matches(subject, DELETE_BY_TEMPLATE);
                        // 分页结果
                        this.maxResults =

                        returnMaxResultsIfFirstKSubjectOrNull(subject);
                    }
                    // 截取条件
                    this.predicate = new Predicate(source.substring(matcher.group().length()), domainClass) {
                        // 截取排序字段条件和普通字段
                        // 例如: AgeAndNameOrderByAgeDesc  ->  AgeAndName AgeDesc
                        String[] parts = split(detectAndSetAllIgnoreCase(predicate), ORDER_BY);
                        // 先通过OR条件进行切割,再将两边的条件使用And进行连接,最终返回这些字段的节点树
                        this.nodes =Arrays.stream(

                        split(parts[0], "Or"))
                                .

                        filter(StringUtils::hasText)
                        // 再将两边的条件使用And进行连接
                                    .

                        map(part ->new

                        OrPart(part, domainClass, alwaysIgnoreCase) {
                            String[] split = split(source, "And");
                            // 保存And的字段
                            this.children = Arrays.stream(split)
                                    .filter(StringUtils::hasText)
                                    .map(part -> new Part(part, domainClass, alwaysIgnoreCase))//
                                    .collect(Collectors.toList());
                        })
                                .

                        collect(Collectors.toList());
                    }
                }
            }
            // 参数个数和解析到的字段条件进行校验
            validate(tree, parameters, method.toString());
            // 创建一个count查询,主要是处理分页
            this.countQuery = new CountQueryPreparer(persistenceProvider, recreationRequired);
            // 如果没有进行分页处理,创建一个QueryPreparer
            // 内部是创建一个CriteriaQuery查询,并设置查询参数
            this.query = tree.isCountProjection() ? countQuery : new QueryPreparer(persistenceProvider, recreationRequired);
        } catch (Exception o_O) {
            throw new IllegalArgumentException(String.format("Failed to create query for method %s! %s", method, o_O.getMessage()), o_O);
        }
    }
}

// 命名查询器
class PropertiesBasedNamedQueries implements NamedQueries {
    // 对应这命名查询的配置文件属性
    // 它是作为一个Bean传入的,是通过PropertiesFactoryBean生成的Bean
    // User.findAllAdultUsers = SELECT u FROM User u WHERE u.id > 1
    private final @NonNull
    Properties properties;

    // 命名查询配置文件jpa-named-queries.properties中是否存在该方法
    // User.findAllAdultUsers=SELECT u FROM User u WHERE u.id > 1
    public boolean hasQuery(String queryName) {
        return properties.containsKey(queryName);
    }

    // 查找命名查询的sql
    // User.findAllAdultUsers=SELECT u FROM User u WHERE u.id > 1
    public String getQuery(String queryName) {
        // 获取到命名查询的sql
        String query = properties.getProperty(queryName);
        // 如果没有找到对应的命名查询,抛出异常
        if (query == null) {
            throw new IllegalArgumentException(String.format(NO_QUERY_FOUND, queryName));
        }
        // 返回命名查询对应的sql
        return query;
    }
}

// 创建Properties的Bean实例
class PropertiesFactoryBean extends PropertiesLoaderSupport implements FactoryBean<Properties> {
    // 需要加载的资源文件路径
    private Resource[] locations;
    // 本身存在的本地变量数据
    protected Properties[] localProperties;
    // Properties单实例
    private Properties singletonInstance;
    if(this.singleton)

    {
        // 所以这个配置就是FactoryBean本身存在的属性变量,与当前需要加载的路径对应的配置进行合并的属性
        this.singletonInstance = createProperties();
    }

    // 创建Properties对象
    protected Properties createProperties() throws IOException {
        return mergeProperties();
    }

    // 合并原有的Properties属性
    protected Properties mergeProperties() throws IOException {
        Properties result = new Properties();
        // 是否允许覆盖本地的配置,默认为false,就是一个执行时机的问题
        // 如果允许覆盖,那么需要先加载当前配置文件,在进行本地合并覆盖
        // 如果不允许覆盖,那么先保存所有的本地变量,然后在记载最新的属性
        if (this.localOverride) {
            // 加载属性
            loadProperties(result);
        }
        // 如果存在本地配置信息,进行覆盖
        if (this.localProperties != null) {
            // 遍历所有的本地配置
            for (Properties localProp : this.localProperties) {
                // 将加载的配置与本地的配置进行合并,重复的进行覆盖
                CollectionUtils.mergePropertiesIntoMap(localProp, result);
            }
        }
        // 是否覆盖本地的配置,默认为false
        if (!this.localOverride) {
            loadProperties(result);
        }
        return result;
    }

    // 加载属性
    protected void loadProperties(Properties props) throws IOException {
        // 是否设置需要加载的属性文件路径
        if (this.locations != null) {
            // 如果存在
            for (Resource location : this.locations) {
                // 加载属性到props中
                PropertiesLoaderUtils.fillProperties(props, new EncodedResource(location, this.fileEncoding), this.propertiesPersister)
                {
                    // 获取流数据
                    InputStream stream = location.getInputStream();
                    // 加载对Properties中
                    props.load(reader);
                }
            }
        }
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值