Gradle 源碼分析(一)

1. 寫(xiě)在前面

在執(zhí)行g(shù)radle命令的時(shí)候芜辕,你是否想過(guò)它是如何運(yùn)作的疾棵。接下來(lái)幾篇文章將從入口開(kāi)始逐步分析 gradle 的啟動(dòng)蕊苗,構(gòu)建流程栗精。(gradle 源碼版本為 5.6.4)。

2. 啟動(dòng)流程

2.1 整體實(shí)現(xiàn)

這里我整理了啟動(dòng)流程的一些主要操作彪蓬,并繪制了調(diào)用鏈的時(shí)序圖寸莫。如果對(duì)源碼不感興趣的同學(xué)只需要看這一部分的內(nèi)容即可。

2.1.1 時(shí)序圖

啟動(dòng)流程時(shí)序圖.png

2.1.2 主要操作

啟動(dòng)階段 Gradle 主要做了下面這些事情档冬。

  1. 下載 gradle wrapper 需要的依賴以及gradle源碼膘茎;
  2. 創(chuàng)建 DefaultServiceRegistry,并注冊(cè)GlobalScopeServices酷誓;
  3. 反射調(diào)用 GlobalScopeServices 的 configure()披坏,注冊(cè) META-INF/services/org.gradle.internal.service.scopes.PluginServiceRegistry 下聲明的 PluginServicesRegistry;
  4. 注冊(cè) CrossBuildSessionScopeServices盐数;
  5. 注冊(cè) BuildTreeScopeServices棒拂;
  6. 創(chuàng)建 DefaultGradleLauncher,調(diào)用 executeTasks()進(jìn)入構(gòu)建階段玫氢;

2.2 源碼分析

回想一下帚屉,如果需要構(gòu)建 apk 文件,是不是可以執(zhí)行 ./gradlew :app:assembleRelease 命令琐旁。而這里調(diào)用的就是 gradlew 這個(gè)腳本文件。gradlew 文件只用關(guān)心最后一行猜绣,前面大部分都是環(huán)境灰殴,參數(shù)等的判斷;

exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

這里的 JAVACMDCLASSPATH 是什么?這個(gè)時(shí)候再帶著疑問(wèn)向前看牺陶。

CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar

if [ -n "$JAVA_HOME" ] ; then
    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
        # IBM's JDK on AIX uses strange locations for the executables
        JAVACMD="$JAVA_HOME/jre/sh/java"
    else
        JAVACMD="$JAVA_HOME/bin/java"
    fi
    if [ ! -x "$JAVACMD" ] ; then
        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
    fi
else
    JAVACMD="java"
    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

可以看到這里的 CLASSPATH 就是工程目錄下的 gradle/wrapper/gradle-wrapper.jar伟阔;而 JAVACMD$JAVA_HOME/bin/javaJAVA_HOME 即環(huán)境變量配置的 JAVA_HOME掰伸。

這么一來(lái) gradlew 最后一行的命令大致上是這樣子的皱炉。

exec /Library/Java/JavaVirtualMachines/jdk1.8.0_261.jdk/Contents/Home/bin/java  -classpath projectDir/gradle/wrapper/gradle-wrapper.jar org.gradle.wrapper.GradleWrapperMain

其實(shí)就是執(zhí)行 gradle-wrapper.jar 里面的 GradleWrapperMainmain(),這就是入口函數(shù)了狮鸭。

2.2.1 下載 Gradle 文件

先來(lái)看看 GradleWrapperMainmain() 合搅。

// GradleWrapperMain.java
public static void main(String[] args) throws Exception {
    // /gradle/wrapper/gradle-wrapper.jar
    File wrapperJar = wrapperJar();
    // /gradle/wrapper/gradle-wrapper.properties
    File propertiesFile = wrapperProperties(wrapperJar);
    // root dir
    File rootDir = rootDir(wrapperJar);

    CommandLineParser parser = new CommandLineParser();
    parser.allowUnknownOptions();
    parser.option(GRADLE_USER_HOME_OPTION, GRADLE_USER_HOME_DETAILED_OPTION).hasArgument();
    parser.option(GRADLE_QUIET_OPTION, GRADLE_QUIET_DETAILED_OPTION);

    SystemPropertiesCommandLineConverter converter = new SystemPropertiesCommandLineConverter();
    converter.configure(parser);

    ParsedCommandLine options = parser.parse(args);

    Properties systemProperties = System.getProperties();
    systemProperties.putAll(converter.convert(options, new HashMap<String, String>()));

    // gradle user home,默認(rèn)為 ~/.gradle
    File gradleUserHome = gradleUserHome(options);

    addSystemProperties(gradleUserHome, rootDir);

    Logger logger = logger(options);
    // 執(zhí)行 WrapperExecutor.execute()
    WrapperExecutor wrapperExecutor = WrapperExecutor.forWrapperPropertiesFile(propertiesFile);
    wrapperExecutor.execute(
            args,
            new Install(logger, new Download(logger, "gradlew", UNKNOWN_VERSION), new PathAssembler(gradleUserHome)),
            new BootstrapMainStarter());
}

這里會(huì)調(diào)用 WrapperExecutorexecute()歧蕉。

// WrapperExecutor.java
public void execute(String[] args, Install install, BootstrapMainStarter bootstrapMainStarter) throws Exception {
    // 這里會(huì)下載 gradle 文件
    File gradleHome = install.createDist(config);
    // 走啟動(dòng)流程
    bootstrapMainStarter.start(args, gradleHome);
}

這里先調(diào)用 InstallcreateDist() 下載 gradle wrapper 需要的依賴以及源碼文件灾部。

// Install.java
public File createDist(final WrapperConfiguration configuration) throws Exception {
    // 下面會(huì)拿 gradle/wrapper/gradle-wrapper.properties 里面定義的一些參數(shù)
    final URI distributionUrl = configuration.getDistribution();
    final String distributionSha256Sum = configuration.getDistributionSha256Sum();

    final PathAssembler.LocalDistribution localDistribution = pathAssembler.getDistribution(configuration);
    final File distDir = localDistribution.getDistributionDir();
    final File localZipFile = localDistribution.getZipFile();

    return exclusiveFileAccessManager.access(localZipFile, new Callable<File>() {
        public File call() throws Exception {
            // 1. 先看本地有沒(méi)有,如果有的話直接返回
            final File markerFile = new File(localZipFile.getParentFile(), localZipFile.getName() + ".ok");
            if (distDir.isDirectory() && markerFile.isFile()) {
                return getAndVerifyDistributionRoot(distDir, distDir.getAbsolutePath());
            }
            
            // 2. 如果需要下載惯退,則進(jìn)行下載
            boolean needsDownload = !localZipFile.isFile();
            URI safeDistributionUrl = Download.safeUri(distributionUrl);

            if (needsDownload) {
                File tmpZipFile = new File(localZipFile.getParentFile(), localZipFile.getName() + ".part");
                tmpZipFile.delete();
                logger.log("Downloading " + safeDistributionUrl);
                // 下載gralde源碼
                download.download(distributionUrl, tmpZipFile);
                tmpZipFile.renameTo(localZipFile);
            }

            List<File> topLevelDirs = listDirs(distDir);
            for (File dir : topLevelDirs) {
                logger.log("Deleting directory " + dir.getAbsolutePath());
                deleteDir(dir);
            }

            verifyDownloadChecksum(configuration.getDistribution().toString(), localZipFile, distributionSha256Sum);

            try {
                // 3.解壓文件
                unzip(localZipFile, distDir);
            } catch (IOException e) {
                logger.log("Could not unzip " + localZipFile.getAbsolutePath() + " to " + distDir.getAbsolutePath() + ".");
                logger.log("Reason: " + e.getMessage());
                throw e;
            }

            File root = getAndVerifyDistributionRoot(distDir, safeDistributionUrl.toString());
            setExecutablePermissions(root);
            markerFile.createNewFile();

            return root;
        }
    });
}

可以看到赌髓,這里會(huì)先查看 ~/.gradle/wrapper/dists/gradle-5.6.4-all/xxx/gradle.5.6.4-all.zip.ok 文件是否存在,如果存在則不需要進(jìn)行下載催跪;如果不存在則需要從 gradle-wrapper.properties 里面定義的 distributionUrl 進(jìn)行下載锁蠕。

2.2.2 創(chuàng)建 DefaultServiceRegistry

中間的調(diào)用鏈就不列出源碼了,對(duì)分析沒(méi)有太大幫助懊蒸,感興趣的可以根據(jù)時(shí)序圖自己去查看源碼荣倾。直接看 BuildActionsFactoryrunBuildInProcess()

// BuildActionsFactory.java
private Runnable runBuildInProcess(StartParameterInternal startParameter, DaemonParameters daemonParameters) {
    // 創(chuàng)建DefaultServiceRegistry
    ServiceRegistry globalServices = ServiceRegistryBuilder.builder()
            .displayName("Global services")
            .parent(loggingServices)
            .parent(NativeServices.getInstance())
            // 添加 GlobalScopeServices
            .provider(new GlobalScopeServices(startParameter.isContinuous()))
            .build();

    // Force the user home services to be stopped first, the dependencies between the user home services and the global services are not preserved currently
    return runBuildAndCloseServices(startParameter, daemonParameters, globalServices.get(BuildExecuter.class), globalServices, globalServices.get(GradleUserHomeScopeServiceRegistry.class));
}

來(lái)看看 ServiceRegistryBuilderbuild()榛鼎。

// ServiceRegistryBuilder.java
public ServiceRegistry build() {
    // 1. 創(chuàng)建 DefaultServiceRegistry
    DefaultServiceRegistry registry = new DefaultServiceRegistry(displayName, parents.toArray(new ServiceRegistry[0]));
    for (Object provider : providers) {
        // 2. 這里會(huì)把 GlobalScopeServices 添加進(jìn)去
        registry.addProvider(provider);
    }
    return registry;
}

這里會(huì)創(chuàng)建 DefaultServiceRegistry 的對(duì)象逃呼,然后調(diào)用 addProvider() 添加 GlobalScopeServices,這兩個(gè)地方是重點(diǎn)者娱。來(lái)看看 DefaultServiceRegistry 的構(gòu)造器和 addProvider() 做了什么抡笼。

// DefaultServiceRegistry.java
public DefaultServiceRegistry(String displayName, ServiceRegistry... parents) {
    // ... 省略一部分代碼
    // 主要是這個(gè)方法
    findProviderMethods(this);
}

public DefaultServiceRegistry addProvider(Object provider) {
    // 也調(diào)用了這個(gè)方法
    findProviderMethods(provider);
}

發(fā)現(xiàn)構(gòu)造器和 addProvider() 都調(diào)用了 findProviderMethods()

// DefaultServiceRegistry.java
private void findProviderMethods(Object target) {
    Class<?> type = target.getClass();
    // 這里會(huì)反射找相應(yīng)的方法
    RelevantMethods methods = RelevantMethods.getMethods(type);
    // ...  省略部分代碼
}

主要看 RelevantMethods.getMethods() 究竟查找了哪些方法黄鳍。

// RelevantMethods.java
public static RelevantMethods getMethods(Class<?> type) {
    // 先看緩存里面有沒(méi)有推姻,如果有則直接返回
    RelevantMethods relevantMethods = METHODS_CACHE.get(type);
    if (relevantMethods == null) {
        // 如果緩存沒(méi)有,則通過(guò)反射獲取相關(guān)方法
        relevantMethods = buildRelevantMethods(type);
        METHODS_CACHE.putIfAbsent(type, relevantMethods);
    }
    return relevantMethods;
}

private static RelevantMethods buildRelevantMethods(Class<?> type) {
    RelevantMethodsBuilder builder = new RelevantMethodsBuilder(type);
    RelevantMethods relevantMethods;
    // 以下三行分別找到對(duì)應(yīng)的方法
    addDecoratorMethods(builder);
    addFactoryMethods(builder);
    addConfigureMethods(builder);
    relevantMethods = builder.build();
    return relevantMethods;
}

// 這里會(huì)解析 configure()
private static void addConfigureMethods(RelevantMethodsBuilder builder) {
    Class<?> type = builder.type;
    Iterator<Method> iterator = builder.remainingMethods.iterator();
    while (iterator.hasNext()) {
        Method method = iterator.next();
        // 尋找返回值為void 的configure()框沟,并添加到 configures 里面
        if (method.getName().equals("configure")) {
            if (!method.getReturnType().equals(Void.TYPE)) {
                throw new ServiceLookupException(String.format("Method %s.%s() must return void.", type.getSimpleName(), method.getName()));
            }
            builder.add(iterator, builder.configurers, method);
        }
    }
}

// 添加工廠方法
private static void addFactoryMethods(RelevantMethodsBuilder builder) {
    Class<?> type = builder.type;
    Iterator<Method> iterator = builder.remainingMethods.iterator();
    while (iterator.hasNext()) {
        Method method = iterator.next();
        // 非 static 的 createXXX() 方法
        if (method.getName().startsWith("create") && !Modifier.isStatic(method.getModifiers())) {
            if (method.getReturnType().equals(Void.TYPE)) {
                throw new ServiceLookupException(String.format("Method %s.%s() must not return void.", type.getSimpleName(), method.getName()));
            }
            // 添加到 factories 里面
            builder.add(iterator, builder.factories, method);
        }
    }
}

// 添加裝飾方法
private static void addDecoratorMethods(RelevantMethodsBuilder builder) {
    Class<?> type = builder.type;
    Iterator<Method> iterator = builder.remainingMethods.iterator();
    while (iterator.hasNext()) {
        Method method = iterator.next();
        // 查找 createXXX() 或 decorateXXX()藏古,傳參和返回值一致的方法
        if (method.getName().startsWith("create") || method.getName().startsWith("decorate")) {
            if (method.getReturnType().equals(Void.TYPE)) {
                throw new ServiceLookupException(String.format("Method %s.%s() must not return void.", type.getSimpleName(), method.getName()));
            }
            if (takesReturnTypeAsParameter(method)) {
                // 添加到 decorators 里面
                builder.add(iterator, builder.decorators, method);
            }
        }
    }
}

可以看到,主要查找了三類方法:

  1. create 開(kāi)頭或者 decorate 開(kāi)頭忍燥,且入?yún)⑴c返回值類型一致的方法(裝飾方法)拧晕;
  2. create 開(kāi)頭又返回值且不是 static 的方法(工廠方法);
  3. configure 方法梅垄;

通過(guò)反射查找完對(duì)應(yīng)的方法后厂捞,再回到 DefaultServiceRegistryfindProviderMethods()

// DefaultServiceRegistry.java
private void findProviderMethods(Object target) {
    Class<?> type = target.getClass();
    RelevantMethods methods = RelevantMethods.getMethods(type);
    // 這里會(huì)遍歷上一步找到的方法
    for (ServiceMethod method : methods.decorators) {
        if (parentServices == null) {
            throw new ServiceLookupException(String.format("Cannot use decorator method %s.%s() when no parent registry is provided.", type.getSimpleName(), method.getName()));
        }
        // 包裝成FactoryMethodService,供get(XXX.class)反射調(diào)用
        ownServices.add(new FactoryMethodService(this, target, method));
    }
    for (ServiceMethod method : methods.factories) {
        // 包裝成FactoryMethodService靡馁,供get(XXX.class)反射調(diào)用
        ownServices.add(new FactoryMethodService(this, target, method));
    }
    // 如果是 configure() 會(huì)直接執(zhí)行欲鹏。
    for (ServiceMethod method : methods.configurers) {
        applyConfigureMethod(method, target);
    }
}

這里通過(guò) RelevantMethodsgetMethods() 查找完方法后,會(huì)進(jìn)行遍歷臭墨,然后將裝飾方法和工廠方法包裝成 FactoryMethodService 對(duì)象赔嚎,后續(xù)通過(guò) get() 調(diào)用的時(shí)候?qū)嶋H上就是通過(guò) FactoryMethodService 進(jìn)行反射調(diào)用對(duì)應(yīng)的裝飾方法或工廠方法創(chuàng)建對(duì)象。

2.2.3 調(diào)用 configure()胧弛,注冊(cè) PluginServiceRegistry

有趣的點(diǎn)在于 GlobalScopeServices 在經(jīng)歷 findProviderMethods() 后會(huì)調(diào)用其 configure()尤误。

// GlobalScopeServices.java
void configure(ServiceRegistration registration, ClassLoaderRegistry classLoaderRegistry) {
    final List<PluginServiceRegistry> pluginServiceFactories = new DefaultServiceLocator(classLoaderRegistry.getRuntimeClassLoader(), classLoaderRegistry.getPluginsClassLoader()).getAll(PluginServiceRegistry.class);
    // ...
}

這里 getAll(PluginServiceRegistry.class) 是在查找 PluginServiceRegistry

// DefaultServiceLocator.java
public <T> List<T> getAll(Class<T> serviceType) throws UnknownServiceException {
    List<ServiceFactory<T>> factories = findFactoriesForServiceType(serviceType);
    // ...
}

private <T> List<ServiceFactory<T>> findFactoriesForServiceType(Class<T> serviceType) {
    return factoriesFor(serviceType, implementationsOf(serviceType));
}

public <T> List<Class<? extends T>> implementationsOf(Class<T> serviceType) {
    // ...
    return findServiceImplementations(serviceType);
    // ...
}

// 主要是這個(gè)方法叶圃,它會(huì)查找 META-INF/services/org.gradle.internal.service.scopes.PluginServiceRegistry這個(gè)文件袄膏,并加載里面聲明的 PluginServiceRegistry
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;
}

根據(jù)調(diào)用鏈,可以看到最終會(huì)查找 META-INF/services/org.gradle.internal.service.scopes.PluginServiceRegistry 這個(gè)文件掺冠,主要記住兩個(gè)關(guān)鍵的 PluginServiceRegistry沉馆,分別是 org.gradle.composite.internal.CompositeBuildServicesorg.gradle.tooling.internal.provider.LauncherServices

PluginServiceRegistry.png

再回到 GlobalScopServicesconfigure()德崭,查找完 PluginServiceRegistry 后斥黑,會(huì)調(diào)用其 registerGlobalServices 完成注冊(cè)。

// GlobalScopeServices.java
void configure(ServiceRegistration registration, ClassLoaderRegistry classLoaderRegistry) {
    final List<PluginServiceRegistry> pluginServiceFactories = new DefaultServiceLocator(classLoaderRegistry.getRuntimeClassLoader(), classLoaderRegistry.getPluginsClassLoader()).getAll(PluginServiceRegistry.class);
    // 調(diào)用 PluginServiceRegistry 的registerGlobalServices
    for (PluginServiceRegistry pluginServiceRegistry : pluginServiceFactories) {
        registration.add(PluginServiceRegistry.class, pluginServiceRegistry);
        pluginServiceRegistry.registerGlobalServices(registration);
    }
}

2.3.4 注冊(cè) CrossBuildSessionScopeServices

分析完上面的流程眉厨,思緒該回到 BuildActionsFactoryrunBuildInProcess()锌奴。

private Runnable runBuildInProcess(StartParameterInternal startParameter, DaemonParameters daemonParameters) {
    ServiceRegistry globalServices = ServiceRegistryBuilder.builder()
            .displayName("Global services")
            .parent(loggingServices)
            .parent(NativeServices.getInstance())
            .provider(new GlobalScopeServices(startParameter.isContinuous()))
            .build();
    // 這里 globalServices.get(BuildExecuter.class) 就是通過(guò)前面存下來(lái)的FactoryMethodService 進(jìn)行反射調(diào)用對(duì)應(yīng)的工廠方法獲取 BuildExecuter對(duì)象
    return runBuildAndCloseServices(startParameter, daemonParameters, globalServices.get(BuildExecuter.class), globalServices, globalServices.get(GradleUserHomeScopeServiceRegistry.class));
}

private Runnable runBuildAndCloseServices(StartParameterInternal startParameter, DaemonParameters daemonParameters, BuildActionExecuter<BuildActionParameters> executer, ServiceRegistry sharedServices, Object... stopBeforeSharedServices) {
    BuildActionParameters parameters = createBuildActionParameters(startParameter, daemonParameters);
    Stoppable stoppable = new CompositeStoppable().add(stopBeforeSharedServices).add(sharedServices);
    // 實(shí)際上創(chuàng)建的是 RunBuildAction 對(duì)象
    return new RunBuildAction(executer, startParameter, clientMetaData(), getBuildStartTime(), parameters, sharedServices, stoppable);
}

這里的 globalServices.get(GradleUserHomeScopeServiceRegistry.class) 就是通過(guò)前面 2.2.2 保存下來(lái)的 FactoryMethodService 反射調(diào)用對(duì)應(yīng)的工廠方法,這里會(huì)調(diào)用到 LauncherServices 內(nèi)部類 ToolingGlobalScopeServicescreateBuildExecuter()憾股。

//ToolingGlobalScopeServices.java
BuildExecuter createBuildExecuter(List<BuildActionRunner> buildActionRunners,
                                  List<SubscribableBuildActionRunnerRegistration> registrations,
                                  ListenerManager listenerManager,
                                  BuildOperationListenerManager buildOperationListenerManager,
                                  TaskInputsListener inputsListener,
                                  StyledTextOutputFactory styledTextOutputFactory,
                                  ExecutorFactory executorFactory,
                                  LoggingManagerInternal loggingManager,
                                  GradleUserHomeScopeServiceRegistry userHomeServiceRegistry,
                                  FileSystemChangeWaiterFactory fileSystemChangeWaiterFactory,
                                  ParallelismConfigurationManager parallelismConfigurationManager
) {
    return new SetupLoggingActionExecuter(
        new SessionFailureReportingActionExecuter(
            new StartParamsValidatingActionExecuter(
                new ParallelismConfigurationBuildActionExecuter(
                    new GradleThreadBuildActionExecuter(
                        new SessionScopeBuildActionExecuter(
                            new SubscribableBuildActionExecuter(
                                new ContinuousBuildActionExecuter(
                                    new BuildTreeScopeBuildActionExecuter(
                                        new InProcessBuildActionExecuter(
                                            new RunAsBuildOperationBuildActionRunner(
                                                new BuildCompletionNotifyingBuildActionRunner(
                                                    new ValidatingBuildActionRunner(
                                                        new BuildOutcomeReportingBuildActionRunner(
                                                            new ChainingBuildActionRunner(buildActionRunners),
                                                            styledTextOutputFactory)))))),
                                fileSystemChangeWaiterFactory,
                                inputsListener,
                                styledTextOutputFactory,
                                executorFactory),
                                    listenerManager,
                                    buildOperationListenerManager,
                                    registrations),
                            userHomeServiceRegistry)),
                    parallelismConfigurationManager)),
            styledTextOutputFactory,
            Time.clock()),
        loggingManager);
}

傳給 RunBuildAction 的是 SetupLoggingActionExecuter 對(duì)象鹿蜀,接著會(huì)在 ParseAndBuildActionexecute() 中調(diào)用 RunBuildActionrun()

// RunBuildAction.java
public void run() {
        // ...
        // 實(shí)際上是調(diào)用了 executer 的 execute()
        BuildActionResult result = executer.execute(
                new ExecuteBuildAction(startParameter),
                new DefaultBuildRequestContext(new DefaultBuildRequestMetaData(clientMetaData, startTime, sharedServices.get(ConsoleDetector.class).isConsoleInput()), new DefaultBuildCancellationToken(), new NoOpBuildEventConsumer()),
                buildActionParameters,
                sharedServices);
        // ...
}

前面說(shuō)了服球,這里的 executerSetupLoggingActionExecuter茴恰,緊接著又是一堆委托調(diào)用,感興趣的可以跟著時(shí)序圖向后看斩熊,就不一一列舉了往枣,這里直接看 SessionScopeBuildActionExecuterexecute()

public BuildActionResult execute(BuildAction action, BuildRequestContext requestContext, BuildActionParameters actionParameters, ServiceRegistry contextServices) {
    StartParameter startParameter = action.getStartParameter();
    final ServiceRegistry userHomeServices = userHomeServiceRegistry.getServicesFor(startParameter.getGradleUserHomeDir());
    // 創(chuàng)建 CrossBuildSessionScopeServices
    CrossBuildSessionScopeServices crossBuildSessionScopeServices = new CrossBuildSessionScopeServices(contextServices, startParameter);
    // 注冊(cè) CrossBuildSessionScopeServices
    ServiceRegistry buildSessionScopeServices = new BuildSessionScopeServices(
        userHomeServices,
        crossBuildSessionScopeServices,
        startParameter,
        requestContext,
        actionParameters.getInjectedPluginClasspath(),
        requestContext.getCancellationToken(),
        requestContext.getClient(),
        requestContext.getEventConsumer()
    );
    // 省略部分代碼
}

這里就是注冊(cè) CrossBuildSessionScopeServices 了粉渠,它也會(huì)執(zhí)行 2.2.2 分析的 findProviderMethods() 流程分冈。

2.3.5 注冊(cè) BuildTreeScopeServices

SessionScopeBuildActionExecuterexecute() 之后會(huì)經(jīng)過(guò)一系列的委托調(diào)用,走到 BuildTreeScopeBuildActionExecuterexecute()霸株。

// BuildTreeScopeBuildActionExecuter.java
public BuildActionResult execute(BuildAction action, BuildRequestContext requestContext, BuildActionParameters actionParameters, ServiceRegistry contextServices) {
    // ...
    BuildTreeScopeServices buildTreeScopeServices = new BuildTreeScopeServices(contextServices);
    // ...
}

execute() 里面會(huì)注冊(cè) BuildTreeScopeServices 雕沉。

2.3.6 創(chuàng)建 DefaultGradleLauncher,調(diào)用 executeTasks()進(jìn)入構(gòu)建階段

經(jīng)過(guò) BuildTreeScopeServicesexecute() 后去件,再省略一系列的委托調(diào)用坡椒,到 InProcessBuildActionExecuterexecute()饺著。

public BuildActionResult execute(final BuildAction action, final BuildRequestContext buildRequestContext, BuildActionParameters actionParameters, ServiceRegistry contextServices) {
    // 這里就是反射獲取的 CompositeBuildServices 的 createIncludedBuildRegistry()
    BuildStateRegistry buildRegistry = contextServices.get(BuildStateRegistry.class);
    // ...
    try {
        // 創(chuàng)建DefaultGradleLauncher。
        RootBuildState rootBuild = buildRegistry.createRootBuild(BuildDefinition.fromStartParameter(action.getStartParameter(), null));
        return rootBuild.run(new Transformer<BuildActionResult, BuildController>() {
            @Override
            public BuildActionResult transform(BuildController buildController) {
                BuildActionRunner.Result result = buildActionRunner.run(action, buildController);
                if (result.getBuildFailure() == null) {
                    return BuildActionResult.of(payloadSerializer.serialize(result.getClientResult()));
                }
                if (buildRequestContext.getCancellationToken().isCancellationRequested()) {
                    return BuildActionResult.cancelled(payloadSerializer.serialize(result.getBuildFailure()));
                }
                return BuildActionResult.failed(payloadSerializer.serialize(result.getClientFailure()));
            }
        });
    } finally {
        buildOperationNotificationValve.stop();
    }
}

這里首先會(huì)通過(guò)反射調(diào)用 CompositeBuildServices 內(nèi)部類 CompositeBuildTreeScopeServicescreateIncludedBuildRegistry() 獲取 BuildStateRegistry肠牲。

// CompositeBuildServices.java
public BuildStateRegistry createIncludedBuildRegistry(CompositeBuildContext context, ProjectStateRegistry projectRegistry, Instantiator instantiator, WorkerLeaseService workerLeaseService, ImmutableModuleIdentifierFactory moduleIdentifierFactory, GradleLauncherFactory gradleLauncherFactory, ListenerManager listenerManager, ServiceRegistry rootServices) {
    IncludedBuildFactory includedBuildFactory = new DefaultIncludedBuildFactory(instantiator, workerLeaseService);
    IncludedBuildDependencySubstitutionsBuilder dependencySubstitutionsBuilder = new IncludedBuildDependencySubstitutionsBuilder(context, moduleIdentifierFactory);
    return new DefaultIncludedBuildRegistry(includedBuildFactory, projectRegistry, dependencySubstitutionsBuilder, gradleLauncherFactory, listenerManager, (BuildTreeScopeServices) rootServices);
}

返回的是 DefaultIncludedBuildRegistry 對(duì)象;緊接著調(diào)用了 DefaultIncludedBuildRegistrycreateRootBuild()靴跛。

// DefaultIncludedBuildRegistry.java
public RootBuildState createRootBuild(BuildDefinition buildDefinition) {
    // ... 
    // 這里會(huì)創(chuàng)建 DefaultRootBuildState
    rootBuild = new DefaultRootBuildState(buildDefinition, gradleLauncherFactory, listenerManager, rootServices);
    // ... 
}

createRootBuild() 里面會(huì)創(chuàng)建 DefaultRootBuildState缀雳,而在 DefaultRootBuildState 的構(gòu)造器里面會(huì)創(chuàng)建 GradleLauncher

// DefaultRootBuildState.java
DefaultRootBuildState(BuildDefinition buildDefinition, GradleLauncherFactory gradleLauncherFactory, ListenerManager listenerManager, BuildTreeScopeServices parentServices) {
    this.listenerManager = listenerManager;
    gradleLauncher = gradleLauncherFactory.newInstance(buildDefinition, this, parentServices);
}

這里調(diào)用 gradleLauncherFactorynewInstance() 創(chuàng)建 GradleLauncher梢睛,gradleLauncherFactory 也是通過(guò)反射調(diào)用 CrossBuildSessionScopeServicescreateGradleLauncherFactory() 獲取的肥印。

// DefaultGradleLauncherFactory.java
public GradleLauncher newInstance(BuildDefinition buildDefinition, RootBuildState build, BuildTreeScopeServices parentRegistry) {
    // ... 
    // 調(diào)用 doNewInstance() 
    DefaultGradleLauncher launcher = doNewInstance(buildDefinition, build, null, parentRegistry, ImmutableList.of(new Stoppable() {
            @Override
            public void stop() {
                rootBuild = null;
            }
        }));
    rootBuild = launcher;
    // ...
    return launcher;
}

private DefaultGradleLauncher doNewInstance(BuildDefinition buildDefinition,
                                            BuildState build,
                                            @Nullable GradleLauncher parent,
                                            BuildTreeScopeServices buildTreeScopeServices,
                                            List<?> servicesToStop) {
    // ... 
    // 創(chuàng)建 DefaultGradleLauncher 對(duì)象
    DefaultGradleLauncher gradleLauncher = new DefaultGradleLauncher(
        gradle,
        serviceRegistry.get(ProjectsPreparer.class),
        serviceRegistry.get(ExceptionAnalyser.class),
        gradle.getBuildListenerBroadcaster(),
        listenerManager.getBroadcaster(BuildCompletionListener.class),
        gradle.getServices().get(BuildWorkExecutor.class),
        serviceRegistry,
        servicesToStop,
        includedBuildControllers,
        settingsPreparer,
        taskExecutionPreparer,
        gradle.getServices().get(InstantExecution.class)
    );
    // ...
    return gradleLauncher;
}

這部分就是創(chuàng)建 DefaultGradleLauncher 了;緊接著又是一系列的委托調(diào)用绝葡,最終會(huì)走到 ChainingBuildActionRunnerrun()深碱。

public Result run(BuildAction action, BuildController buildController) {
    for (BuildActionRunner runner : runners) {
        Result result = runner.run(action, buildController);
        if (result.hasResult()) {
            return result;
        }
    }
    return Result.nothing();
}

而這里只是簡(jiǎn)單的遍歷傳入的 runners,調(diào)用其 run()藏畅;這里的 runners 是通過(guò)反射調(diào)用的 LaunchersServices 內(nèi)部類 ToolingGlobalScopeServicescreateExecuteBuildActionRunner()敷硅,即 ExecuteBuildActionRunner 對(duì)象。

// LaunchersServices.java
ExecuteBuildActionRunner createExecuteBuildActionRunner() {
      return new ExecuteBuildActionRunner();
}

ExecuteBuildActionRunnerrun() 也只是調(diào)用 buildControllerrun()愉阎。

// ExecuteBuildActionRunner.java
public Result run(BuildAction action, BuildController buildController) {
    // ...
    buildController.run();
}

buildController 是在 InProcessBuildActionExecuter 里面調(diào)用 DefaultRootBuildStaterun() 創(chuàng)建的 GradleBuildController 對(duì)象绞蹦,那么來(lái)看它的 run()

public GradleInternal run() {
    return doBuild(GradleInternal.BuildType.TASKS, new Action<GradleLauncher>() {
        @Override
        public void execute(@Nonnull GradleLauncher gradleLauncher) {
            gradleLauncher.executeTasks();
        }
    });
}

這里最終會(huì)調(diào)用到 gradleLauncherexecuteTasks() 進(jìn)入構(gòu)建階段榜旦;至此 gradle 的啟動(dòng)流程就分析完了幽七。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市溅呢,隨后出現(xiàn)的幾起案子澡屡,更是在濱河造成了極大的恐慌,老刑警劉巖咐旧,帶你破解...
    沈念sama閱讀 216,591評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件驶鹉,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡休偶,警方通過(guò)查閱死者的電腦和手機(jī)梁厉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)踏兜,“玉大人词顾,你說(shuō)我怎么就攤上這事〖钭保” “怎么了肉盹?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,823評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)疹尾。 經(jīng)常有香客問(wèn)我上忍,道長(zhǎng)骤肛,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,204評(píng)論 1 292
  • 正文 為了忘掉前任窍蓝,我火速辦了婚禮腋颠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘吓笙。我一直安慰自己淑玫,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布面睛。 她就那樣靜靜地躺著絮蒿,像睡著了一般。 火紅的嫁衣襯著肌膚如雪叁鉴。 梳的紋絲不亂的頭發(fā)上土涝,一...
    開(kāi)封第一講書(shū)人閱讀 51,190評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音幌墓,去河邊找鬼但壮。 笑死,一個(gè)胖子當(dāng)著我的面吹牛常侣,可吹牛的內(nèi)容都是我干的茵肃。 我是一名探鬼主播,決...
    沈念sama閱讀 40,078評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼袭祟,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼验残!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起巾乳,我...
    開(kāi)封第一講書(shū)人閱讀 38,923評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤您没,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后胆绊,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體氨鹏,經(jīng)...
    沈念sama閱讀 45,334評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評(píng)論 2 333
  • 正文 我和宋清朗相戀三年压状,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了仆抵。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,727評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡种冬,死狀恐怖镣丑,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情娱两,我是刑警寧澤莺匠,帶...
    沈念sama閱讀 35,428評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站十兢,受9級(jí)特大地震影響趣竣,放射性物質(zhì)發(fā)生泄漏摇庙。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評(píng)論 3 326
  • 文/蒙蒙 一遥缕、第九天 我趴在偏房一處隱蔽的房頂上張望卫袒。 院中可真熱鬧,春花似錦单匣、人聲如沸玛臂。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,672評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至讽营,卻和暖如春虎忌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背橱鹏。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,826評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工膜蠢, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人莉兰。 一個(gè)月前我還...
    沈念sama閱讀 47,734評(píng)論 2 368
  • 正文 我出身青樓挑围,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親糖荒。 傳聞我的和親對(duì)象是個(gè)殘疾皇子杉辙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 本文來(lái)自于CSDN博客,作者:晏博捶朵,已獲授權(quán)蜘矢,版權(quán)歸原作者所有,未經(jīng)作者同意综看,請(qǐng)勿轉(zhuǎn)載品腹。 背景 陸陸續(xù)續(xù)一年多,總...
    passiontim閱讀 853評(píng)論 0 5
  • argus-apm-gradle工程定義了一個(gè)gradle plugin红碑,主要有以下兩個(gè)作用: 支持AOP編程舞吭,方...
    David_zhou閱讀 514評(píng)論 0 0
  • 轉(zhuǎn)自:http://wind-bell27.iteye.com/blog/1969930 先講基本步驟,如下: 去...
    alexpdh閱讀 1,876評(píng)論 0 3
  • 久違的晴天析珊,家長(zhǎng)會(huì)羡鸥。 家長(zhǎng)大會(huì)開(kāi)好到教室時(shí),離放學(xué)已經(jīng)沒(méi)多少時(shí)間了忠寻。班主任說(shuō)已經(jīng)安排了三個(gè)家長(zhǎng)分享經(jīng)驗(yàn)兄春。 放學(xué)鈴聲...
    飄雪兒5閱讀 7,522評(píng)論 16 22
  • 今天感恩節(jié)哎,感謝一直在我身邊的親朋好友锡溯。感恩相遇赶舆!感恩不離不棄哑姚。 中午開(kāi)了第一次的黨會(huì),身份的轉(zhuǎn)變要...
    迷月閃星情閱讀 10,562評(píng)論 0 11