二十四,java设计模式面试题和答案

public class CompositeEnvironmentRepository implements EnvironmentRepository {

//仓库列表

protected List environmentRepositories;

@Override

public Environment findOne(String application, String profile, String label) {

//Environment 是对配置文件名,环境,分支等封装对象

Environment env = new Environment(application, new String[]{profile}, label, null, null);

//是不是只配置了一个仓库

if(environmentRepositories.size() == 1) {

//这里调用的是MultipleJGitEnvironmentRepository#findOne

Environment envRepo = environmentRepositories.get(0).findOne(application, profile, label);

//把加载到的配置文件的内容设置给Environment

env.addAll(envRepo.getPropertySources());

//版本号

env.setVersion(envRepo.getVersion());

//状态

env.setState(envRepo.getState());

} else {

//如果配置了多个仓库,循环通过repo.findOne去下载配置

for (EnvironmentRepository repo : environmentRepositories) {

env.addAll(repo.findOne(application, profile, label).getPropertySources());

}

}

return env;

}

这里把配置文件名,环境名,分支名封装成Environment 对象,同时该对象也用来接收结果。然后判断了一下是否配置了多个仓库,多个仓库就循环调用findOne方法加载配置,我们这里只配置了一个仓库,走的是MultipleJGitEnvironmentRepository的findOne方法,然后把结果设置给Environment 并返回Environment。

注意:env.addAll(envRepo.getPropertySources()); 这行代码,PropertySources就是加载到的配置文件的内容了。

继续往后面走,代码来到 MultipleJGitEnvironmentRepository#findOne 方法中

@Override

public Environment findOne(String application, String profile, String label) {

…省略…

//这个getRepository方法中对url中的类似{application}的占位符做了一些替换

JGitEnvironmentRepository candidate = getRepository(this, application, profile,

label);

if (label == null) {

//如果label是null,默认使用master作为分支

label = candidate.getDefaultLabel();

}

if (candidate == this) {

//默认走这

return super.findOne(application, profile, label);

}

return candidate.findOne(application, profile, label);

}

该方法中对URL中的占位符如:{application},{label}等进行替换,然后判断如果label是空的,就使用master作为默认label。最后调用super.findOne方法,此时代码来到其父类 AbstractScmEnvironmentRepository#findOne 方法

@Override

public synchronized Environment findOne(String application, String profile, String label) {

//加载本机的环境存储库

NativeEnvironmentRepository delegate = new NativeEnvironmentRepository(getEnvironment(),

new NativeEnvironmentProperties());

//加载Locations ,Locations是对本地配置文件的封装

Locations locations = getLocations(application, profile, label);

//locations.getLocations()得到本地配置文件路径

delegate.setSearchLocations(locations.getLocations());

//调用 NativeEnvironmentRepository #findOne方法加载配置

Environment result = delegate.findOne(application, profile, “”);

//把版本号和label设置给result

result.setVersion(locations.getVersion());

result.setLabel(label);

//执行本地仓库的清理工作

return this.cleaner.clean(result, getWorkingDirectory().toURI().toString(),

getUri());

}

该方法做了这么几件事情:

  1. 把ConfigurableEnvironment交给一个NativeEnvironmentRepository对象,ConfigurableEnvironment中有当前配置中心微服务的原始配置。

  2. 调用 getLocations 方法得到Locations ,它封装了配置文件的 application,profile,label,version ,和本地存储远程拉取下来的配置文件的位置。如:file:/C:/Users/whale/AppData/Local/Temp/config-repo-8104345609176998816/

  3. 把配置文件的地址交给NativeEnvironmentRepository ,然后调用其findOne方法

  4. 最后执行clean清理

getLocations 加载本地配置

我们先看一下 getLocations 方法是怎么加载本地配置文件的,代码来到JGitEnvironmentRepository#getLocations

@Override

public synchronized Locations getLocations(String application, String profile,

String label) {

if (label == null) {

//默认使用master分支

label = this.defaultLabel;

}

//刷新配置,这个代码回去远程拉取最新的配置文件

String version = refresh(label);

//调用 getSearchLocations 处理一下本地配置文件地址,把结果封装成Locations

return new Locations(application, profile, label, version,

getSearchLocations(getWorkingDirectory(), application, profile, label));

}

这里调用了 refresh方法下载配置文件,然后调用 getSearchLocations 找到本地下载的配置文件地址,封装成Locations返回。

重点看一下 refresh方法,代码来到JGitEnvironmentRepository#refresh方法中

/**准备工作目录

  • Get the working directory ready.

*/

public String refresh(String label) {

Git git = null;

try {

//【1】创建Git客户端

git = createGitClient();

//【2】判断是否要从远程拉取配置文件

if (shouldPull(git)) {

//【3】执行配置文件拉取动作

FetchResult fetchStatus = fetch(git, label);

if (deleteUntrackedBranches && fetchStatus != null) {

deleteUntrackedLocalBranches(fetchStatus.getTrackingRefUpdates(), git);

}

// checkout after fetch so we can get any new branches, tags, ect.

//【4】执行checkout操作,切到master分支

checkout(git, label);

//判断仓库的所有分支是否包含当前分支

if (isBranch(git, label)) {

// merge results from fetch

//【5】执行merge操作

merge(git, label);

if (!isClean(git, label)) {

logger.warn(“The local repository is dirty or ahead of origin. Resetting”

  • " it to origin/" + label + “.”);

resetHard(git, label, LOCAL_BRANCH_REF_PREFIX + label);

}

}

}

else {

// nothing to update so just checkout

checkout(git, label);

}

//【6】始终返回当前HEAD作为版本 , 把版本号返回

// always return what is currently HEAD as the version

return git.getRepository().findRef(“HEAD”).getObjectId().getName();

}

…省略…

}

//创建Git客户端

private Git createGitClient() throws IOException, GitAPIException {

//工作目录加锁

File lock = new File(getWorkingDirectory(), “.git/index.lock”);

//锁是否存在

if (lock.exists()) {

// The only way this can happen is if another JVM (e.g. one that

// crashed earlier) created the lock. We can attempt to recover by

// wiping the slate clean.

logger.info("Deleting stale JGit lock file at " + lock);

//删除锁

lock.delete();

}

//工作中的配置文件是否创造

if (new File(getWorkingDirectory(), “.git”).exists()) {

//打开Git仓库

return openGitRepository();

}

else {

//拷贝Git仓库

return copyRepository();

}

}

JGitEnvironmentRepository#refresh方法挺复杂的,简单点锁就是根据URL把Git仓库中的配置文件fetch到本地,然后进行checkout,merge等等。然后把本地配置文件的地址。

代码还要回到 .AbstractScmEnvironmentRepository#findOne ,刚才跟的是getLocations方法

@Override

public synchronized Environment findOne(String application, String profile, String label) {

NativeEnvironmentRepository delegate = new NativeEnvironmentRepository(getEnvironment(),

new NativeEnvironmentProperties());

//查找配置的地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值