1. 寫在前面
在 Gradle源碼分析(二)一文中,我們分析了Gradle構(gòu)建流程的
LoadSettings
階段,這里將分析Configure
階段(gradle 源碼版本為 5.6.4)。
2. Configure
2.1 整體實(shí)現(xiàn)
這里我整理了 Configure
階段的一些主要操作,并繪制了調(diào)用鏈的時(shí)序圖。如果對(duì)源碼不感興趣的同學(xué)只需要看這一部分的內(nèi)容即可。
2.1.1 時(shí)序圖
2.1.2 主要操作
Configure
階段 Gradle 主要做了下面這些事情瞻凤。
- 創(chuàng)建 root project 和 sub project,它們都是
DefaultProject
對(duì)象世杀; - 調(diào)用
BuildListener
的projectsLoaded()
阀参; - 開始配置 root project,調(diào)用
ProjectEvaluationListener
的beforeEvaluate()
瞻坝,apply 默認(rèn)插件蛛壳,編譯執(zhí)行 build.gradle 文件,調(diào)用ProjectEvaluationListener
的afterEvaluate()
所刀; - 遍歷 sub project衙荐,重復(fù) 3 中配置 root project 的過程;
- 調(diào)用
BuildListener
的projectEvaluated()
浮创。
2.2 源碼分析
2.2.1 創(chuàng)建 Root Project 和 Sub Project
Configure
過程是發(fā)生在 DefaultGradleLauncher
的 prepareProjects()
中忧吟,先來看看它的源碼。
// DefaultGradleLauncher.java
private void prepareProjects() {
if (stage == Stage.LoadSettings) {
// 配置 projects
projectsPreparer.prepareProjects(gradle);
// 將狀態(tài)設(shè)置為 Configure
stage = Stage.Configure;
}
}
這里的 projectsPreparer
是通過反射調(diào)用的 BuildScopeServices
的 createBuildConfigurer()
斩披。
// BuildScopeServices.java
protected ProjectsPreparer createBuildConfigurer(ProjectConfigurer projectConfigurer, BuildStateRegistry buildStateRegistry, BuildLoader buildLoader, ListenerManager listenerManager, BuildOperationExecutor buildOperationExecutor) {
ModelConfigurationListener modelConfigurationListener = listenerManager.getBroadcaster(ModelConfigurationListener.class);
return new BuildOperatingFiringProjectsPreparer(
new DefaultProjectsPreparer(
projectConfigurer,
buildStateRegistry,
buildLoader,
modelConfigurationListener,
buildOperationExecutor),
buildOperationExecutor);
}
即 BuildOperatingFiringProjectsPreparer
對(duì)象溜族,并在構(gòu)造器中傳入了 DefaultProjectsPreparer
的對(duì)象。毫無疑問垦沉,BuildOperatingFiringProjectsPreparer
的 prepareProjects()
最后會(huì)調(diào)用到 DefaultProjectsPreparer
的 prepareProjects()
煌抒,所以直接看 DefaultProjectsPreparer
的 prepareProjects()
。
// DefaultProjectsPreparer.java
public void prepareProjects(GradleInternal gradle) {
// ...
buildLoader.load(gradle.getSettings(), gradle);
// ...
}
這里的 buildLoader
是通過反射調(diào)用的 BuildScoeServices
的 createBuildLoader()
乡话。
// BuildScoeServices.java
protected BuildLoader createBuildLoader(IGradlePropertiesLoader propertiesLoader, IProjectFactory projectFactory, BuildOperationExecutor buildOperationExecutor) {
return new NotifyingBuildLoader(
new ProjectPropertySettingBuildLoader(
propertiesLoader,
new InstantiatingBuildLoader(
projectFactory
)
),
buildOperationExecutor
);
}
來看看 NotifyingBuildLoader
的 load()
摧玫。
// NotifyingBuildLoader.java
public void load(final SettingsInternal settings, final GradleInternal gradle) {
buildOperationExecutor.call(new CallableBuildOperation<Void>() {
@Override
public Void call(BuildOperationContext context) {
// 1. 調(diào)用 ProjectPropertySettingBuildLoader 的 load()
buildLoader.load(settings, gradle);
}
});
buildOperationExecutor.run(new RunnableBuildOperation() {
@Override
public void run(BuildOperationContext context) {
// 2. load()走完后耳奕,會(huì)執(zhí)行 BuildListener 的 projectesLoaded()绑青,記住這里诬像,后面會(huì)提到。
gradle.getBuildListenerBroadcaster().projectsLoaded(gradle);
}
});
}
這里調(diào)用了 ProjectPropertySettingBuildLoader
的 load()
闸婴。
// ProjectPropertySettingBuildLoader.java
public void load(SettingsInternal settings, GradleInternal gradle) {
// 1. 調(diào)用 InstantiatingBuildLoader 的 load()
buildLoader.load(settings, gradle);
// 2. 解析 project 目錄下的 gradle.properties 配置的屬性坏挠,簡單了解一下
setProjectProperties(gradle.getRootProject(), new CachingPropertyApplicator());
}
這里調(diào)用了 InstantiatingBuildLoader
的 load()
。
// InstantiatingBuildLoader.java
public void load(SettingsInternal settings, GradleInternal gradle) {
load(settings.getRootProject(), settings.getDefaultProject(), gradle, settings.getRootClassLoaderScope());
}
private void load(ProjectDescriptor rootProjectDescriptor, ProjectDescriptor defaultProject, GradleInternal gradle, ClassLoaderScope buildRootClassLoaderScope) {
createProjects(rootProjectDescriptor, gradle, buildRootClassLoaderScope);
attachDefaultProject(defaultProject, gradle);
}
private void attachDefaultProject(ProjectDescriptor defaultProject, GradleInternal gradle) {
gradle.setDefaultProject(gradle.getRootProject().getProjectRegistry().getProject(defaultProject.getPath()));
}
private void createProjects(ProjectDescriptor rootProjectDescriptor, GradleInternal gradle, ClassLoaderScope buildRootClassLoaderScope) {
// 1. 配置 root project
ProjectInternal rootProject = projectFactory.createProject(rootProjectDescriptor, null, gradle, buildRootClassLoaderScope.createChild("root-project"), buildRootClassLoaderScope);
// 設(shè)置 root project
gradle.setRootProject(rootProject);
// 調(diào)用 addProjects() 遍歷 sub project邪乍,創(chuàng)建 sub project
addProjects(rootProject, rootProjectDescriptor, gradle, buildRootClassLoaderScope);
}
private void addProjects(ProjectInternal parent, ProjectDescriptor parentProjectDescriptor, GradleInternal gradle, ClassLoaderScope buildRootClassLoaderScope) {
// 遍歷 sub project降狠,創(chuàng)建 sub project
for (ProjectDescriptor childProjectDescriptor : parentProjectDescriptor.getChildren()) {
ProjectInternal childProject = projectFactory.createProject(childProjectDescriptor, parent, gradle, parent.getClassLoaderScope().createChild("project-" + childProjectDescriptor.getName()), buildRootClassLoaderScope);
addProjects(childProject, childProjectDescriptor, gradle, buildRootClassLoaderScope);
}
}
可以看到,這里主要是通過的 projectFactory
的 createProject()
來創(chuàng)建 Project
對(duì)象的庇楞;而 projectFactory
是通過反射調(diào)用的 BuildScopeServices
的 createProjectFactory()
榜配。
// BuildScopeServices.java
protected IProjectFactory createProjectFactory(Instantiator instantiator, ProjectRegistry<ProjectInternal> projectRegistry) {
return new ProjectFactory(instantiator, projectRegistry);
}
即 ProjectFactory
對(duì)象,來看看其 createProject()
做了什么事情吕晌。
// ProjectFactory.java
public DefaultProject createProject(ProjectDescriptor projectDescriptor, ProjectInternal parent, GradleInternal gradle, ClassLoaderScope selfClassLoaderScope, ClassLoaderScope baseClassLoaderScope) {
// 獲取到 build.gradle
File buildFile = projectDescriptor.getBuildFile();
// 加載 build.gradle
TextResource resource = resourceLoader.loadFile("build file", buildFile);
ScriptSource source = new TextResourceScriptSource(resource);
// 創(chuàng)建 DefaultProject 對(duì)象
DefaultProject project = instantiator.newInstance(DefaultProject.class,
projectDescriptor.getName(),
parent,
projectDescriptor.getProjectDir(),
buildFile,
source,
gradle,
gradle.getServiceRegistryFactory(),
selfClassLoaderScope,
baseClassLoaderScope
);
// ...
if (parent != null) {
// sub project 添加到其 parent 里面
parent.addChildProject(project);
}
// 注冊(cè) project
projectRegistry.addProject(project);
return project;
}
這里會(huì)創(chuàng)建 project 對(duì)象蛋褥,然后注冊(cè) project。
2.2.2 調(diào)用 BuildListener 的 projectsLoaded()
創(chuàng)建完 root project 和 sub project 后睛驳,思緒該回到之前提到過的 NotifyingBuildLoader
的 load()
了烙心。
// NotifyingBuildLoader.java
public void load(final SettingsInternal settings, final GradleInternal gradle) {
buildOperationExecutor.call(new CallableBuildOperation<Void>() {
@Override
public BuildOperationDescriptor.Builder description() {
@Override
public Void call(BuildOperationContext context) {
// 這里往下走的是前面創(chuàng)建 root project 和 sub project 的過程
buildLoader.load(settings, gradle);
return null
}
});
buildOperationExecutor.run(new RunnableBuildOperation() {
@Override
public void run(BuildOperationContext context) {
// 走完 load() 后,回調(diào)用 BuildListener 的 projectsLoaded()
gradle.getBuildListenerBroadcaster().projectsLoaded(gradle);
}
});
}
可以看到在 NotifyingBuildLoader
的 load()
里面在走完 load()
流程后乏沸,會(huì)執(zhí)行 BuildListener
的 projectsLoaded()
淫茵。
2.2.3 配置 Project
看完 load()
過程,該回到 DefaultProjectPreparer
的 prepareProjects()
繼續(xù)往下看了蹬跃。
// DefaultProjectPreparer.java
public void prepareProjects(GradleInternal gradle) {
maybeInformAboutIncubatingMode(gradle);
buildLoader.load(gradle.getSettings(), gradle);
// ...
// 如果設(shè)置了參數(shù) --configure-on-demand 進(jìn)行按需構(gòu)建匙瘪,則只會(huì)配置 root project 和 tasks 需要的 projects
if (gradle.getStartParameter().isConfigureOnDemand()) {
projectConfigurer.configure(gradle.getRootProject());
} else {
// 如果沒有設(shè)置按需配置,則默認(rèn)會(huì)構(gòu)建所有的 projects
projectConfigurer.configureHierarchy(gradle.getRootProject());
// 這里記一下蝶缀,也是調(diào)用生命周期方法
new ProjectsEvaluatedNotifier(buildOperationExecutor).notify(gradle);
}
}
可以看到在 load()
之后辆苔,會(huì)判斷是否有 --configure-on-demand
參數(shù)配置,如果配置了這個(gè)參數(shù)扼劈,gradle 會(huì)進(jìn)行按需配置(只會(huì)構(gòu)建 root project 和 tasks 需要的 projects)驻啤;如果沒有配置,則默認(rèn)會(huì)構(gòu)建所有的 projects荐吵,它是包含 root projects 的配置過程的骑冗,所以這里看 configureHierarchy()
即可。projectConfigurer
是通過反射調(diào)用的 BuildScopeServices
的 createProjectConfigurer()
先煎。
// BuildScopeServices.java
protected ProjectConfigurer createProjectConfigurer(BuildCancellationToken cancellationToken) {
return new TaskPathProjectEvaluator(cancellationToken);
}
即 TaskPathProjectEvaluator
對(duì)象贼涩,來看看其 configureHierarchy()
。
// TaskPathProjectEvaluator.java
public void configure(ProjectInternal project) {
if (cancellationToken.isCancellationRequested()) {
throw new BuildCancelledException();
}
project.evaluate();
}
@Override
public void configureHierarchy(ProjectInternal project) {
// 1. 先配置 root project薯蝎,這個(gè)和 --configure-on-demand 是一樣的
configure(project);
// 2. 然后遍歷 sub project遥倦,配置 sub project
for (Project sub : project.getSubprojects()) {
configure((ProjectInternal) sub);
}
}
可以看到 configureHierarchy()
會(huì)先走 --configure-on-demand
的配置過程,先配置 root project, 然后再配置所有的 sub project袒哥。這里的 project
即前面創(chuàng)建的 DefaultProject
缩筛,來看看其 evaluate()
。
// DefaultProject.java
public DefaultProject evaluate() {
getProjectEvaluator().evaluate(this, state);
return this;
}
public ProjectEvaluator getProjectEvaluator() {
if (projectEvaluator == null) {
projectEvaluator = services.get(ProjectEvaluator.class);
}
return projectEvaluator;
}
這里的 projectEvaluator
是通過反射調(diào)用的 BuildScopeServices
的 createProjectEvaluator()
堡称。
// BuildScopeServices.java
protected ProjectEvaluator createProjectEvaluator(BuildOperationExecutor buildOperationExecutor, CachingServiceLocator cachingServiceLocator, ScriptPluginFactory scriptPluginFactory) {
ConfigureActionsProjectEvaluator withActionsEvaluator = new ConfigureActionsProjectEvaluator(
// 這里需要注意一下瞎抛,一般project都會(huì)有默認(rèn)的任務(wù),其實(shí)就是這個(gè)類在作怪却紧,它里面執(zhí)行的時(shí)候桐臊,會(huì)給project apply 默認(rèn)的插件,然后插件里面會(huì)創(chuàng)建任務(wù)晓殊,所以每個(gè)project 才會(huì)有一些默認(rèn)的任務(wù)
PluginsProjectConfigureActions.from(cachingServiceLocator),
// 這里是解析執(zhí)行 build.gradle的地方
new BuildScriptProcessor(scriptPluginFactory),
new DelayedConfigurationActions()
);
return new LifecycleProjectEvaluator(buildOperationExecutor, withActionsEvaluator);
}
需要注意一下断凶,這里在創(chuàng)建 ConfigureActionsProjectEvaluator
的時(shí)候傳入了 PluginsProjectConfigureActions.from()
,這個(gè)東西有點(diǎn)意思滴嘞巫俺,來看看它做了什么懒浮。
// PluginsProjectConfigureActions.java
public static ProjectConfigureAction from(ServiceLocator serviceLocator) {
return of(ProjectConfigureAction.class, serviceLocator);
}
public static <T extends Action<ProjectInternal>> ProjectConfigureAction of(Class<T> serviceType,
ServiceLocator serviceLocator) {
return new PluginsProjectConfigureActions(
ImmutableList.<Action<ProjectInternal>>copyOf(
serviceLocator.getAll(serviceType)));
}
這里的 serviceLocator
是通過反射調(diào)用的 GlobalScopeServices
的 createPluginsServiceLocator()
。
// GlobalScopeServices.java
CachingServiceLocator createPluginsServiceLocator(ClassLoaderRegistry registry) {
return CachingServiceLocator.of(
new DefaultServiceLocator(registry.getPluginsClassLoader())
);
}
直接看 DefaultServiceLocator
的 getAll()
识藤。
// DefaultServiceLocator.java
public <T> List<T> getAll(Class<T> serviceType) throws UnknownServiceException {
List<ServiceFactory<T>> factories = findFactoriesForServiceType(serviceType);
ArrayList<T> services = new ArrayList<T>();
for (ServiceFactory<T> factory : factories) {
services.add(factory.create());
}
return services;
}
private <T> List<ServiceFactory<T>> findFactoriesForServiceType(Class<T> serviceType) {
return factoriesFor(serviceType, implementationsOf(serviceType));
}
public <T> List<Class<? extends T>> implementationsOf(Class<T> serviceType) {
try {
return findServiceImplementations(serviceType);
} catch (ServiceLookupException e) {
throw e;
} catch (Exception e) {
throw new ServiceLookupException(String.format("Could not determine implementation classes for service '%s'.", serviceType.getName()), e);
}
}
private <T> List<Class<? extends T>> findServiceImplementations(Class<T> serviceType) throws IOException {
String resourceName = "META-INF/services/" + serviceType.getName();
Set<String> implementationClassNames = new HashSet<String>();
List<Class<? extends T>> implementations = new ArrayList<Class<? extends T>>();
for (ClassLoader classLoader : classLoaders) {
Enumeration<URL> resources = classLoader.getResources(resourceName);
while (resources.hasMoreElements()) {
URL resource = resources.nextElement();
List<String> implementationClassNamesFromResource;
try {
implementationClassNamesFromResource = extractImplementationClassNames(resource);
if (implementationClassNamesFromResource.isEmpty()) {
throw new RuntimeException(String.format("No implementation class for service '%s' specified.", serviceType.getName()));
}
} catch (Throwable e) {
throw new ServiceLookupException(String.format("Could not determine implementation class for service '%s' specified in resource '%s'.", serviceType.getName(), resource), e);
}
for (String implementationClassName : implementationClassNamesFromResource) {
if (implementationClassNames.add(implementationClassName)) {
try {
Class<?> implClass = classLoader.loadClass(implementationClassName);
if (!serviceType.isAssignableFrom(implClass)) {
throw new RuntimeException(String.format("Implementation class '%s' is not assignable to service class '%s'.", implementationClassName, serviceType.getName()));
}
implementations.add(implClass.asSubclass(serviceType));
} catch (Throwable e) {
throw new ServiceLookupException(String.format("Could not load implementation class '%s' for service '%s' specified in resource '%s'.", implementationClassName, serviceType.getName(), resource), e);
}
}
}
}
}
return implementations;
}
這個(gè)過程有沒有一點(diǎn)點(diǎn)的熟悉砚著,不就是我們?cè)?Gradle 源碼分析(一) 里面分析 PluginServiceRegistry
的注冊(cè)流程一樣的嗎,只不過那邊是傳入的 PluginServiceRegistry.class
痴昧,這里傳入的是 ProjectConfigureAction.class
稽穆,所以實(shí)際上這個(gè)流程是在找 META-INF/services/org.gradle.configuration.project.ProjectConfigureAction 文件下配置的 ProjectConfigureAction
。
這里有三個(gè)比較重要的 ProjectConfigureAction
赶撰。
BuildInitAutoApplyAction
WrapperPluginAutoApplyAction
HelpTasksAutoApplyAction
一個(gè)一個(gè)來看舌镶,它們究竟做了什么。
2.2.3.1 BuildInitAutoApplyAction
先來看看 BuildInitAutoApplyAction
的源碼豪娜。
// BuildInitAutoApplyAction.java
public class BuildInitAutoApplyAction implements ProjectConfigureAction {
@Override
public void execute(final ProjectInternal project) {
project.getPluginManager().apply("org.gradle.build-init");
}
}
這里給 project
添加了插件 org.gradle.build-init
餐胀,如果你寫過 gradle 插件,那么一定清楚注冊(cè)插件的地方是在 META-INF/gradle-plugins 下面瘤载。
它對(duì)應(yīng)的是 BuildInitPlugin
類否灾,來看看它的源碼。
// BuildInitPlugin.java
public class BuildInitPlugin implements Plugin<Project> {
@Override
public void apply(final Project project) {
// 如果是 root project鸣奔,注冊(cè) init task
if (project.getParent() == null) {
project.getTasks().register("init", InitBuild.class, new Action<InitBuild>() {
@Override
public void execute(InitBuild initBuild) {
initBuild.setGroup("Build Setup");
initBuild.setDescription("Initializes a new Gradle build.");
initBuild.onlyIf(new Spec<Task>() {
@Override
public boolean isSatisfiedBy(Task element) {
Object skippedMsg = reasonToSkip(project);
if (skippedMsg != null) {
project.getLogger().warn((String) skippedMsg);
return false;
}
return true;
}
});
initBuild.dependsOn(new Callable<String>() {
@Override
public String call() throws Exception {
if (reasonToSkip(project) == null) {
return "wrapper";
} else {
return null;
}
}
});
}
});
}
}
}
這個(gè)插件會(huì)給 root project 注冊(cè) init Task墨技。
2.2.3.2 WrapperPluginAutoApplyAction
來看看 WrapperPluginAutoApplyAction
的源碼。
public class WrapperPluginAutoApplyAction implements ProjectConfigureAction {
@Override
public void execute(ProjectInternal project) {
project.getPluginManager().apply("org.gradle.wrapper");
}
}
可以看到挎狸,它給 project 添加了插件 org.gradle.wrapper
扣汪,同樣的在 META-INF/gradle-plugins 下搜索這個(gè)插件的注冊(cè)文件。
它對(duì)應(yīng)的是 WrapperPlugin
锨匆,來看看其源碼崭别。
// WrapperPlugin.java
public class WrapperPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
// 給root project 注冊(cè) wrapper task
if (project.getParent() == null) {
project.getTasks().register("wrapper", Wrapper.class, new Action<Wrapper>() {
@Override
public void execute(Wrapper wrapper) {
wrapper.setGroup("Build Setup");
wrapper.setDescription("Generates Gradle wrapper files.");
}
});
}
}
}
可以看到,這里給 root project 注冊(cè) wrapper task。
2.2.3.3 HelpTasksAutoApplyAction
最后來看看 HelpTasksAutoApplyAction
的源碼茅主。
// HelpTasksAutoApplyAction.java
public class HelpTasksAutoApplyAction implements ProjectConfigureAction {
@Override
public void execute(ProjectInternal project) {
project.getPluginManager().apply("org.gradle.help-tasks");
}
}
這里給 project 注冊(cè)了插件 org.gradle.help-tasks舞痰,同樣在 META-INF/gradle-plugins 下搜索這個(gè)插件的注冊(cè)文件。
它對(duì)應(yīng)的是 HelpTasksPlugin
暗膜,來看看其源碼。
// HelpTasksPlugin.java
public void apply(final ProjectInternal project) {
final TaskContainerInternal tasks = project.getTasks();
// static classes are used for the actions to avoid implicitly dragging project/tasks into the model registry
String projectName = project.toString();
// 注冊(cè) help task
tasks.register(ProjectInternal.HELP_TASK, Help.class, new HelpAction());
// 注冊(cè) projects task
tasks.register(ProjectInternal.PROJECTS_TASK, ProjectReportTask.class, new ProjectReportTaskAction(projectName));
// 注冊(cè) tasks task
tasks.register(ProjectInternal.TASKS_TASK, TaskReportTask.class, new TaskReportTaskAction(projectName, project.getChildProjects().isEmpty()));
// 注冊(cè) properties task
tasks.register(PROPERTIES_TASK, PropertyReportTask.class, new PropertyReportTaskAction(projectName));
// 注冊(cè) dependencyInsight task
tasks.register(DEPENDENCY_INSIGHT_TASK, DependencyInsightReportTask.class, new DependencyInsightReportTaskAction(projectName));
// 注冊(cè) dependencies task
tasks.register(DEPENDENCIES_TASK, DependencyReportTask.class, new DependencyReportTaskAction(projectName));
// 注冊(cè) buildEnvironment task
tasks.register(BuildEnvironmentReportTask.TASK_NAME, BuildEnvironmentReportTask.class, new BuildEnvironmentReportTaskAction(projectName));
// 注冊(cè) components task
tasks.register(COMPONENTS_TASK, ComponentReport.class, new ComponentReportAction(projectName));
// 注冊(cè) model task
tasks.register(MODEL_TASK, ModelReport.class, new ModelReportAction(projectName));
// 注冊(cè) dependentComponents task
tasks.register(DEPENDENT_COMPONENTS_TASK, DependentComponentsReport.class, new DependentComponentsReportAction(projectName));
}
可以看到這里給所有的 project 注冊(cè)了許多任務(wù)鞭衩,這也是經(jīng)常說的 project 會(huì)有一些默認(rèn)任務(wù)学搜,它就是通過這個(gè)插件進(jìn)行注冊(cè)的。
經(jīng)過這個(gè)小插曲论衍,思緒該回到 BuildScopeService
的 createProjectEvaluator()
了瑞佩。
// BuildScopeService.java
protected ProjectEvaluator createProjectEvaluator(BuildOperationExecutor buildOperationExecutor, CachingServiceLocator cachingServiceLocator, ScriptPluginFactory scriptPluginFactory) {
ConfigureActionsProjectEvaluator withActionsEvaluator = new ConfigureActionsProjectEvaluator(
PluginsProjectConfigureActions.from(cachingServiceLocator),
new BuildScriptProcessor(scriptPluginFactory),
new DelayedConfigurationActions()
);
return new LifecycleProjectEvaluator(buildOperationExecutor, withActionsEvaluator);
}
來看看 LifecycleProjectEvaluator
的 evaluate()
。
// LifecycleProjectEvaluator.java
public void evaluate(final ProjectInternal project, final ProjectStateInternal state) {
if (state.isUnconfigured()) {
buildOperationExecutor.run(new EvaluateProject(project, state));
}
}
// EvaluateProject (內(nèi)部類)
public void run(final BuildOperationContext context) {
project.getMutationState().withMutableState(new Runnable() {
@Override
public void run() {
try {
// 1. 將 project 狀態(tài)設(shè)置為 IN_BEFORE_EVALUATE
state.toBeforeEvaluate();
// 2. 調(diào)用 ProjectEvaluationListener 的 beforeEvaluate()
buildOperationExecutor.run(new NotifyBeforeEvaluate(project, state));
if (!state.hasFailure()) {
// 3. 將 project 的狀態(tài)設(shè)置為 IN_EVALUATE
state.toEvaluate();
try {
// 4. 調(diào)用 ConfigureActionsProjectEvaluator 的 evaluate()
delegate.evaluate(project, state);
} catch (Exception e) {
addConfigurationFailure(project, state, e, context);
} finally {
// 5. 將 project 狀態(tài)設(shè)置為 IN_AFTER_EVALUATE
state.toAfterEvaluate();
// 6. 調(diào)用 ProjectEvaluationListener 的 afterEvaluate()
buildOperationExecutor.run(new NotifyAfterEvaluate(project, state));
}
}
if (state.hasFailure()) {
state.rethrowFailure();
} else {
context.setResult(ConfigureProjectBuildOperationType.RESULT);
}
} finally {
// 7. 將 project 狀態(tài)設(shè)置為 CONFIGURED
state.configured();
}
}
});
}
// NotifyBeforeEvaluate(內(nèi)部類)
public void run(BuildOperationContext context) {
try {
project.getProjectEvaluationBroadcaster().beforeEvaluate(project);
context.setResult(NotifyProjectBeforeEvaluatedBuildOperationType.RESULT);
} catch (Exception e) {
addConfigurationFailure(project, state, e, context);
}
}
// NotifyAfterEvaluate (內(nèi)部類)
public void run(BuildOperationContext context) {
ProjectEvaluationListener nextBatch = project.getProjectEvaluationBroadcaster();
Action<ProjectEvaluationListener> fireAction = new Action<ProjectEvaluationListener>() {
@Override
public void execute(ProjectEvaluationListener listener) {
listener.afterEvaluate(project, state);
}
};
// ...
}
可以看到這里主要做了如下事情:
- 將 project 的狀態(tài)設(shè)置為
IN_BEFORE_EVALUATE
坯台; - 調(diào)用
ProjectEvaluationListener
的beforeEvaluate()
炬丸; - 將 project 的狀態(tài)設(shè)置為
IN_EVALUATE
; - 調(diào)用
ConfigureActionsProjectEvaluator
的evaluate()
蜒蕾; - 將 project 的狀態(tài)設(shè)置為
IN_AFTER_EVALUATE
稠炬; - 調(diào)用
ProjectEvaluationListener
的afterEvaluate()
; - 將 project 的狀態(tài)設(shè)置為
CONFIGURED
咪啡。
接下來看 ConfigureActionsProjectEvaluator
的 evaluate()
首启。
// ConfigureActionsProjectEvaluator.java
public void evaluate(ProjectInternal project, ProjectStateInternal state) {
for (ProjectConfigureAction configureAction : configureActions) {
configureAction.execute(project);
}
}
這里調(diào)用了 configureActions
的 execute()
,也就是前面在創(chuàng)建 ConfigureActionsProjectEvaluator
時(shí)傳入的 PluginsProjectConfigureActions.from(cachingServiceLocator)
和 BuildScriptProcessor
的 execute()
撤摸;前者已經(jīng)分析了毅桃,是給 project 注冊(cè)一些任務(wù);而后者就是解析執(zhí)行 build.gradle 了准夷,來看看其源碼钥飞。
// BuildScriptProcessor.java
public void execute(final ProjectInternal project) {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Evaluating {} using {}.", project, project.getBuildScriptSource().getDisplayName());
}
final Timer clock = Time.startTimer();
try {
final ScriptPlugin configurer = configurerFactory.create(project.getBuildScriptSource(), project.getBuildscript(), project.getClassLoaderScope(), project.getBaseClassLoaderScope(), true);
project.getMutationState().withMutableState(new Runnable() {
@Override
public void run() {
configurer.apply(project);
}
});
}
}
到這里,root project 和 sub project 也就配置完了衫嵌。
2.2.4 調(diào)用 BuildListener 的 projectsEvaluated()
回到 DefaultProjectPreparer
的 prepareProjects()
读宙,接著 configureHierarchy()
往后看。
// DefaultProjectPreparer.java
public void prepareProjects(GradleInternal gradle) {
maybeInformAboutIncubatingMode(gradle);
buildLoader.load(gradle.getSettings(), gradle);
if (gradle.getParent() == null) {
buildRegistry.beforeConfigureRootBuild();
}
if (gradle.getStartParameter().isConfigureOnDemand()) {
projectConfigurer.configure(gradle.getRootProject());
} else {
projectConfigurer.configureHierarchy(gradle.getRootProject());
// 創(chuàng)建 ProjectsEvaluatedNotifier 楔绞,調(diào)用 notify()
new ProjectsEvaluatedNotifier(buildOperationExecutor).notify(gradle);
}
}
它創(chuàng)建了 ProjectsEvaluatedNotifier
论悴,并調(diào)用了 notify()
。
// ProjectsEvaluatedNotifier.java
public void notify(GradleInternal gradle) {
buildOperationExecutor.run(new NotifyProjectsEvaluatedListeners(gradle));
}
// NotifyProjectsEvaluatedListeners(內(nèi)部類)
private class NotifyProjectsEvaluatedListeners implements RunnableBuildOperation {
@Override
public void run(BuildOperationContext context) {
gradle.getBuildListenerBroadcaster().projectsEvaluated(gradle);
}
}
這里最終調(diào)用了 BuildListener
的 projectsEvaluated()
墓律;最后回到 DefaultGradleLauncher
的 prepareProjects()
膀估。
// DefaultGradleLauncher.java
private void prepareProjects() {
if (stage == Stage.LoadSettings) {
projectsPreparer.prepareProjects(gradle);
// 設(shè)置狀態(tài)為 Configure
stage = Stage.Configure;
}
}
執(zhí)行完 prepareProjects()
后,會(huì)將狀態(tài)設(shè)置為 Configure
耻讽。至此察纯,Gradle 的 Configure
階段就分析完了。