Gradle 源码分析(三)

1. 写在前面

Gradle源码分析(二)一文中,我们分析了Gradle构建流程的 LoadSettings 阶段,这里将分析 Configure 阶段(gradle 源码版本为 5.6.4)。

2. Configure

2.1 整体实现

这里我整理了 Configure 阶段的一些主要操作,并绘制了调用链的时序图。如果对源码不感兴趣的同学只需要看这一部分的内容即可。

2.1.1 时序图

Configure时序图.png

2.1.2 主要操作

Configure 阶段 Gradle 主要做了下面这些事情。

  1. 创建 root project 和 sub project,它们都是 DefaultProject 对象;
  2. 调用 BuildListenerprojectsLoaded()
  3. 开始配置 root project,调用 ProjectEvaluationListenerbeforeEvaluate(),apply 默认插件,编译执行 build.gradle 文件,调用 ProjectEvaluationListenerafterEvaluate()
  4. 遍历 sub project,重复 3 中配置 root project 的过程;
  5. 调用 BuildListenerprojectEvaluated()

2.2 源码分析

2.2.1 创建 Root Project 和 Sub Project

Configure 过程是发生在 DefaultGradleLauncherprepareProjects() 中,先来看看它的源码。

// DefaultGradleLauncher.java
private void prepareProjects() {
    if (stage == Stage.LoadSettings) {
        // 配置 projects
        projectsPreparer.prepareProjects(gradle);
        // 将状态设置为 Configure
        stage = Stage.Configure;
    }
}

这里的 projectsPreparer 是通过反射调用的 BuildScopeServicescreateBuildConfigurer()

// 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 对象,并在构造器中传入了 DefaultProjectsPreparer 的对象。毫无疑问,BuildOperatingFiringProjectsPreparerprepareProjects() 最后会调用到 DefaultProjectsPreparerprepareProjects(),所以直接看 DefaultProjectsPreparerprepareProjects()

// DefaultProjectsPreparer.java
public void prepareProjects(GradleInternal gradle) {
    // ...
    buildLoader.load(gradle.getSettings(), gradle);
    // ...
}

这里的 buildLoader 是通过反射调用的 BuildScoeServicescreateBuildLoader()

// BuildScoeServices.java
protected BuildLoader createBuildLoader(IGradlePropertiesLoader propertiesLoader, IProjectFactory projectFactory, BuildOperationExecutor buildOperationExecutor) {
    return new NotifyingBuildLoader(
        new ProjectPropertySettingBuildLoader(
            propertiesLoader,
            new InstantiatingBuildLoader(
                projectFactory
            )
        ),
        buildOperationExecutor
    );
}

来看看 NotifyingBuildLoaderload()

// NotifyingBuildLoader.java
public void load(final SettingsInternal settings, final GradleInternal gradle) {
    buildOperationExecutor.call(new CallableBuildOperation<Void>() {

        @Override
        public Void call(BuildOperationContext context) {
            // 1. 调用 ProjectPropertySettingBuildLoader 的 load()
            buildLoader.load(settings, gradle);
        }
    });
    buildOperationExecutor.run(new RunnableBuildOperation() {
        @Override
        public void run(BuildOperationContext context) {
            // 2. load()走完后,会执行 BuildListener 的 projectesLoaded(),记住这里,后面会提到。
            gradle.getBuildListenerBroadcaster().projectsLoaded(gradle);
        }
    });
}

这里调用了 ProjectPropertySettingBuildLoaderload()

// ProjectPropertySettingBuildLoader.java
public void load(SettingsInternal settings, GradleInternal gradle) {
    // 1. 调用 InstantiatingBuildLoader 的 load()
    buildLoader.load(settings, gradle);
    // 2. 解析 project 目录下的 gradle.properties 配置的属性,简单了解一下
    setProjectProperties(gradle.getRootProject(), new CachingPropertyApplicator());
}

这里调用了 InstantiatingBuildLoaderload()

// 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);
    // 设置 root project
    gradle.setRootProject(rootProject);
    // 调用 addProjects() 遍历 sub project,创建 sub project
    addProjects(rootProject, rootProjectDescriptor, gradle, buildRootClassLoaderScope);
}

private void addProjects(ProjectInternal parent, ProjectDescriptor parentProjectDescriptor, GradleInternal gradle, ClassLoaderScope buildRootClassLoaderScope) {
    // 遍历 sub project,创建 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);
    }
}

可以看到,这里主要是通过的 projectFactorycreateProject() 来创建 Project 对象的;而 projectFactory 是通过反射调用的 BuildScopeServicescreateProjectFactory()

// BuildScopeServices.java
protected IProjectFactory createProjectFactory(Instantiator instantiator, ProjectRegistry<ProjectInternal> projectRegistry) {
    return new ProjectFactory(instantiator, projectRegistry);
}

ProjectFactory 对象,来看看其 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);
    // 创建 DefaultProject 对象
    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);
    }
    // 注册 project
    projectRegistry.addProject(project);

    return project;
}

这里会创建 project 对象,然后注册 project。

2.2.2 调用 BuildListener 的 projectsLoaded()

创建完 root project 和 sub project 后,思绪该回到之前提到过的 NotifyingBuildLoaderload() 了。

// 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) {
            // 这里往下走的是前面创建 root project 和 sub project 的过程
            buildLoader.load(settings, gradle);
            return null
        }
    });
    buildOperationExecutor.run(new RunnableBuildOperation() {
        @Override
        public void run(BuildOperationContext context) {
            // 走完 load() 后,回调用 BuildListener 的 projectsLoaded()
            gradle.getBuildListenerBroadcaster().projectsLoaded(gradle);
        }
    });
}

可以看到在 NotifyingBuildLoaderload() 里面在走完 load() 流程后,会执行 BuildListenerprojectsLoaded()

2.2.3 配置 Project

看完 load() 过程,该回到 DefaultProjectPreparerprepareProjects() 继续往下看了。

// DefaultProjectPreparer.java
public void prepareProjects(GradleInternal gradle) {
    maybeInformAboutIncubatingMode(gradle);

    buildLoader.load(gradle.getSettings(), gradle);
    // ...
    // 如果设置了参数 --configure-on-demand 进行按需构建,则只会配置 root project 和 tasks 需要的 projects
    if (gradle.getStartParameter().isConfigureOnDemand()) {
        projectConfigurer.configure(gradle.getRootProject());
    } else {
        // 如果没有设置按需配置,则默认会构建所有的 projects
        projectConfigurer.configureHierarchy(gradle.getRootProject());
        // 这里记一下,也是调用生命周期方法
        new ProjectsEvaluatedNotifier(buildOperationExecutor).notify(gradle);
    }
}

可以看到在 load() 之后,会判断是否有 --configure-on-demand 参数配置,如果配置了这个参数,gradle 会进行按需配置(只会构建 root project 和 tasks 需要的 projects);如果没有配置,则默认会构建所有的 projects,它是包含 root projects 的配置过程的,所以这里看 configureHierarchy() 即可。projectConfigurer 是通过反射调用的 BuildScopeServicescreateProjectConfigurer()

// BuildScopeServices.java
protected ProjectConfigurer createProjectConfigurer(BuildCancellationToken cancellationToken) {
    return new TaskPathProjectEvaluator(cancellationToken);
}

TaskPathProjectEvaluator 对象,来看看其 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,这个和 --configure-on-demand 是一样的
    configure(project);
    // 2. 然后遍历 sub project,配置 sub project
    for (Project sub : project.getSubprojects()) {
        configure((ProjectInternal) sub);
    }
}

可以看到 configureHierarchy() 会先走 --configure-on-demand 的配置过程,先配置 root project, 然后再配置所有的 sub project。这里的 project 即前面创建的 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 是通过反射调用的 BuildScopeServicescreateProjectEvaluator()

// BuildScopeServices.java
protected ProjectEvaluator createProjectEvaluator(BuildOperationExecutor buildOperationExecutor, CachingServiceLocator cachingServiceLocator, ScriptPluginFactory scriptPluginFactory) {
    ConfigureActionsProjectEvaluator withActionsEvaluator = new ConfigureActionsProjectEvaluator(
        // 这里需要注意一下,一般project都会有默认的任务,其实就是这个类在作怪,它里面执行的时候,会给project apply 默认的插件,然后插件里面会创建任务,所以每个project 才会有一些默认的任务
        PluginsProjectConfigureActions.from(cachingServiceLocator),
        // 这里是解析执行 build.gradle的地方
        new BuildScriptProcessor(scriptPluginFactory),
        new DelayedConfigurationActions()
    );
    return new LifecycleProjectEvaluator(buildOperationExecutor, withActionsEvaluator);
}

需要注意一下,这里在创建 ConfigureActionsProjectEvaluator 的时候传入了 PluginsProjectConfigureActions.from() ,这个东西有点意思滴嘞,来看看它做了什么。

// 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 是通过反射调用的 GlobalScopeServicescreatePluginsServiceLocator()

// GlobalScopeServices.java
CachingServiceLocator createPluginsServiceLocator(ClassLoaderRegistry registry) {
    return CachingServiceLocator.of(
        new DefaultServiceLocator(registry.getPluginsClassLoader())
    );
}

直接看 DefaultServiceLocatorgetAll()

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

这个过程有没有一点点的熟悉,不就是我们在 Gradle 源码分析(一) 里面分析 PluginServiceRegistry 的注册流程一样的吗,只不过那边是传入的 PluginServiceRegistry.class,这里传入的是 ProjectConfigureAction.class,所以实际上这个流程是在找 META-INF/services/org.gradle.configuration.project.ProjectConfigureAction 文件下配置的 ProjectConfigureAction

ProjectConfigureAction.png

这里有三个比较重要的 ProjectConfigureAction

  • BuildInitAutoApplyAction
  • WrapperPluginAutoApplyAction
  • HelpTasksAutoApplyAction

一个一个来看,它们究竟做了什么。

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 插件,那么一定清楚注册插件的地方是在 META-INF/gradle-plugins 下面。

org.gradle.build-init.png

它对应的是 BuildInitPlugin 类,来看看它的源码。

// BuildInitPlugin.java
public class BuildInitPlugin implements Plugin<Project> {
    @Override
    public void apply(final Project project) {
        // 如果是 root project,注册 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;
                            }
                        }
                    });
                }
            });
        }
    }
}

这个插件会给 root project 注册 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 下搜索这个插件的注册文件。

org.gradle.wrapper.png

它对应的是 WrapperPlugin,来看看其源码。

// WrapperPlugin.java
public class WrapperPlugin implements Plugin<Project> {
    @Override
    public void apply(Project project) {
        // 给root project 注册 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 注册 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 注册了插件 org.gradle.help-tasks,同样在 META-INF/gradle-plugins 下搜索这个插件的注册文件。


org.gradle.help-tasks.png

它对应的是 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();
        // 注册 help task
        tasks.register(ProjectInternal.HELP_TASK, Help.class, new HelpAction());
        // 注册 projects task
        tasks.register(ProjectInternal.PROJECTS_TASK, ProjectReportTask.class, new ProjectReportTaskAction(projectName));
        // 注册 tasks task
        tasks.register(ProjectInternal.TASKS_TASK, TaskReportTask.class, new TaskReportTaskAction(projectName, project.getChildProjects().isEmpty()));
        // 注册 properties task
        tasks.register(PROPERTIES_TASK, PropertyReportTask.class, new PropertyReportTaskAction(projectName));
        // 注册 dependencyInsight task
        tasks.register(DEPENDENCY_INSIGHT_TASK, DependencyInsightReportTask.class, new DependencyInsightReportTaskAction(projectName));
        // 注册 dependencies task
        tasks.register(DEPENDENCIES_TASK, DependencyReportTask.class, new DependencyReportTaskAction(projectName));
        // 注册 buildEnvironment task
        tasks.register(BuildEnvironmentReportTask.TASK_NAME, BuildEnvironmentReportTask.class, new BuildEnvironmentReportTaskAction(projectName));
        // 注册 components task
        tasks.register(COMPONENTS_TASK, ComponentReport.class, new ComponentReportAction(projectName));
        // 注册 model task
        tasks.register(MODEL_TASK, ModelReport.class, new ModelReportAction(projectName));
        // 注册 dependentComponents task
        tasks.register(DEPENDENT_COMPONENTS_TASK, DependentComponentsReport.class, new DependentComponentsReportAction(projectName));
    }

可以看到这里给所有的 project 注册了许多任务,这也是经常说的 project 会有一些默认任务,它就是通过这个插件进行注册的。

经过这个小插曲,思绪该回到 BuildScopeServicecreateProjectEvaluator() 了。

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

来看看 LifecycleProjectEvaluatorevaluate()

// LifecycleProjectEvaluator.java
public void evaluate(final ProjectInternal project, final ProjectStateInternal state) {
    if (state.isUnconfigured()) {
        buildOperationExecutor.run(new EvaluateProject(project, state));
    }
}

// EvaluateProject (内部类)
public void run(final BuildOperationContext context) {
    project.getMutationState().withMutableState(new Runnable() {
        @Override
        public void run() {
            try {
                // 1. 将 project 状态设置为 IN_BEFORE_EVALUATE
                state.toBeforeEvaluate();
                // 2. 调用 ProjectEvaluationListener 的 beforeEvaluate()
                buildOperationExecutor.run(new NotifyBeforeEvaluate(project, state));

                if (!state.hasFailure()) {
                    // 3. 将 project 的状态设置为 IN_EVALUATE
                    state.toEvaluate();
                    try {
                        // 4. 调用 ConfigureActionsProjectEvaluator 的 evaluate()
                        delegate.evaluate(project, state);
                    } catch (Exception e) {
                        addConfigurationFailure(project, state, e, context);
                    } finally {
                        // 5. 将 project 状态设置为 IN_AFTER_EVALUATE
                        state.toAfterEvaluate();
                        // 6. 调用 ProjectEvaluationListener 的 afterEvaluate()
                        buildOperationExecutor.run(new NotifyAfterEvaluate(project, state));
                    }
                }

                if (state.hasFailure()) {
                    state.rethrowFailure();
                } else {
                    context.setResult(ConfigureProjectBuildOperationType.RESULT);
                }
            } finally {
                // 7. 将 project 状态设置为 CONFIGURED
                state.configured();
            }
        }
    });
}

// NotifyBeforeEvaluate(内部类)
public void run(BuildOperationContext context) {
    try {
        project.getProjectEvaluationBroadcaster().beforeEvaluate(project);
        context.setResult(NotifyProjectBeforeEvaluatedBuildOperationType.RESULT);
    } catch (Exception e) {
        addConfigurationFailure(project, state, e, context);
    }
}

// NotifyAfterEvaluate (内部类)
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);
        }
    };
    // ...
}

可以看到这里主要做了如下事情:

  1. 将 project 的状态设置为 IN_BEFORE_EVALUATE
  2. 调用 ProjectEvaluationListenerbeforeEvaluate()
  3. 将 project 的状态设置为 IN_EVALUATE
  4. 调用 ConfigureActionsProjectEvaluatorevaluate()
  5. 将 project 的状态设置为 IN_AFTER_EVALUATE
  6. 调用 ProjectEvaluationListenerafterEvaluate()
  7. 将 project 的状态设置为 CONFIGURED

接下来看 ConfigureActionsProjectEvaluatorevaluate()

// ConfigureActionsProjectEvaluator.java
public void evaluate(ProjectInternal project, ProjectStateInternal state) {
    for (ProjectConfigureAction configureAction : configureActions) {
        configureAction.execute(project);
    }
}

这里调用了 configureActionsexecute(),也就是前面在创建 ConfigureActionsProjectEvaluator 时传入的 PluginsProjectConfigureActions.from(cachingServiceLocator)BuildScriptProcessorexecute();前者已经分析了,是给 project 注册一些任务;而后者就是解析执行 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 调用 BuildListener 的 projectsEvaluated()

回到 DefaultProjectPreparerprepareProjects(),接着 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());
        // 创建 ProjectsEvaluatedNotifier ,调用 notify()
        new ProjectsEvaluatedNotifier(buildOperationExecutor).notify(gradle);
    }
}

它创建了 ProjectsEvaluatedNotifier,并调用了 notify()

// ProjectsEvaluatedNotifier.java
public void notify(GradleInternal gradle) {
    buildOperationExecutor.run(new NotifyProjectsEvaluatedListeners(gradle));
}

// NotifyProjectsEvaluatedListeners(内部类)
private class NotifyProjectsEvaluatedListeners implements RunnableBuildOperation {
    @Override
    public void run(BuildOperationContext context) {
        gradle.getBuildListenerBroadcaster().projectsEvaluated(gradle);
    }
}

这里最终调用了 BuildListenerprojectsEvaluated();最后回到 DefaultGradleLauncherprepareProjects()

// DefaultGradleLauncher.java
private void prepareProjects() {
    if (stage == Stage.LoadSettings) {
        projectsPreparer.prepareProjects(gradle);
        // 设置状态为 Configure
        stage = Stage.Configure;
    }
}

执行完 prepareProjects() 后,会将状态设置为 Configure。至此,Gradle 的 Configure 阶段就分析完了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,039评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,223评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,916评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,009评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,030评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,011评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,934评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,754评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,202评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,433评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,590评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,321评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,917评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,568评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,738评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,583评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,482评论 2 352