国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專(zhuān)欄INFORMATION COLUMN

swoft| 源碼解讀系列二: 啟動(dòng)階段, swoft 都干了些啥?

hqman / 2970人閱讀

摘要:源碼解讀系列二啟動(dòng)階段都干了些啥閱讀框架源碼了解啟動(dòng)階段的那些事兒小伙伴剛接觸的時(shí)候會(huì)感覺(jué)壓力有點(diǎn)大更直觀的說(shuō)法是難開(kāi)發(fā)組是不贊成難這個(gè)說(shuō)法的的代碼都是實(shí)現(xiàn)的而又是世界上最好的語(yǔ)言的代碼閱讀起來(lái)是很輕松的之后開(kāi)發(fā)組會(huì)用系列源碼解讀文章深

date: 2018-8-01 14:22:17
title: swoft| 源碼解讀系列二: 啟動(dòng)階段, swoft 都干了些啥?
description: 閱讀 sowft 框架源碼, 了解 sowft 啟動(dòng)階段的那些事兒

小伙伴剛接觸 swoft 的時(shí)候會(huì)感覺(jué) 壓力有點(diǎn)大, 更直觀的說(shuō)法是 . 開(kāi)發(fā)組是不贊成 這個(gè)說(shuō)法的, swoft 的代碼都是 php 實(shí)現(xiàn)的, 而 php 又是 世界上最好的語(yǔ)言, swoft 的代碼閱讀起來(lái)是很輕松的.

之后開(kāi)發(fā)組會(huì)用 系列源碼 解讀文章, 深入解析 swoft. 我們相信, 這會(huì)成為一段輕松之旅.

swoft 源碼解讀系列一: 好難! swoft demo 都跑不起來(lái)怎么破? docker 了解一下唄~
swoft 源碼解讀系列二: 啟動(dòng)階段, swoft 都干了些啥?

附上社區(qū)小伙伴 隨風(fēng) 制作的流程圖:

程序入口

看過(guò) 官方文檔-服務(wù)啟動(dòng)與管理 章節(jié), 就知道 swoft 的入口時(shí) php bin/swoft start, 用來(lái)啟動(dòng) http server. 運(yùn)行這個(gè)命令, 就為我們打開(kāi)了新世界的大門(mén)

root@e38a7e5aff40 /v/w/s/swoft# ps aux
PID   USER     TIME   COMMAND
    1 root       0:00 php -a
  708 root       0:01 php-swoft master process (bin/swoft)
  709 root       0:00 php-swoft manager process
  711 root       0:01 php-swoft task process
  712 root       0:01 php-swoft worker process
  713 root       0:49 php-swoft reload process
  779 root       0:00 ps aux

熟悉 swoole-wiki 的小伙伴, 就能看到熟悉的:

master 進(jìn)程

manager 進(jìn)程

worker 進(jìn)程

task-worker 進(jìn)程

swoole-wiki 上的 運(yùn)行流程圖進(jìn)程/線程結(jié)構(gòu)圖 值得細(xì)細(xì)品味, 這是我們之后理解和使用 swoole 進(jìn)行服務(wù)器開(kāi)發(fā)的基礎(chǔ), 這里按下暫時(shí)不表.

而我們?yōu)榱伺?swoft啟動(dòng)階段都干了些啥, 可以直接運(yùn)行 php bin/swoft, 慢慢 調(diào)試/輸出 即可. 是的, 沒(méi)有什么高級(jí)技巧, var_dump() + die() 即可

使用工具閱讀源碼的小技巧

沒(méi)錯(cuò), 這個(gè)工具就是 phpstorm, 沒(méi)使用 phpstorm 的小伙伴趕緊用起來(lái), 下面以 window 下的快捷鍵為例:

快捷鍵說(shuō)明: C->ctrl A->alt S->shift

C-b / C-鼠標(biāo)點(diǎn)擊: 跳轉(zhuǎn)到方法/函數(shù)定義的地方

C-A-左右方向鍵: 切換光標(biāo)前后所在的位置

C-e: 查看最近打開(kāi)的文件

C-q: 查看函數(shù)的注釋說(shuō)明(知道寫(xiě)注釋有多重要了吧)

C-p: 查看函數(shù)的參數(shù)(還是注釋的重要性)

還有很多好用的功能, 請(qǐng)查看菜單欄的 navigate 菜單欄, 去發(fā)現(xiàn)驚喜吧~

PS: 注釋! 注釋! 注釋!

入口源碼: bootstrap

bin/swoft 文件很簡(jiǎn)單:

#!/usr/bin/env php
run();

我們先來(lái)看 bin/bootstrap.php:

require_once dirname(__DIR__) . "/vendor/autoload.php";
require_once dirname(__DIR__) . "/config/define.php";

// init the factory of bean
SwoftBeanBeanFactory::init();

/* @var SwoftBootstrapBootsBootable $bootstrap*/
$bootstrap = SwoftApp::getBean(SwoftBootstrapBootstrap::class);
$bootstrap->bootstrap();

第一步加載 composer 的 autoload 文件, 使用 composer 的同學(xué)應(yīng)該都知道吧, 不過(guò)你知道 autoload 的原理么?

第二步是 config/define.php 文件, 我們進(jìn)去看看:

// Project base path
! defined("BASE_PATH") && define("BASE_PATH", dirname(__DIR__, 1));

// Register alias
$aliases = [
    "@root"       => BASE_PATH,
];

SwoftApp::setAliases($aliases);

做了 2 件事:

定義 PHP 常量

swoft 的別名機(jī)制

swoft 的第一個(gè)特性 -- 別名機(jī)制 來(lái)了. 挺新鮮的詞兒, 本質(zhì)很簡(jiǎn)單 -- 字符串替換 而已, 比如上面我們?cè)O(shè)置 @root, 我們直接打印看看:

$tmp = SwoftApp::getAlias("@root");
var_dump($tmp);die;

root@e38a7e5aff40 /v/w/s/swoft# php bin/swoft
string(21) "/var/www/swoole/swoft"

使用看看:

$tmp1 = SwoftApp::getAlias("@root");
$tmp2 = SwoftApp::getAlias("@root/foo/bar");
var_dump($tmp1, $tmp2);die;

root@e38a7e5aff40 /v/w/s/swoft# php bin/swoft
string(21) "/var/www/swoole/swoft"
string(29) "/var/www/swoole/swoft/foo/bar"

目前 swoft 中的別名機(jī)制在用在 文件目錄/路徑 上, 熟悉 yii框架 的小伙伴知道, yii中別名機(jī)制用的場(chǎng)景更多一些, 還能拼接 url 等地方. 不過(guò)不管使用多少場(chǎng)景, 本質(zhì)都是 字符串替換.

那為什么不直接使用 PHP常量 這種常規(guī)方式, 而要使用別名機(jī)制呢? 別名機(jī)制不是更優(yōu)雅么

框架核心: BeanFactory

到了框架的核心部分了, 閱讀這塊的代碼要有耐心一點(diǎn):

// init the factory of bean
SwoftBeanBeanFactory::init();

進(jìn)入 init(), 先看第一個(gè):

$properties = self::getProperties(); // 獲取 property 配置
var_dump($properties);die;

看源碼和調(diào)試驗(yàn)證輔助: 讀取 config/properties 下的配置(文件), merge 到同一個(gè)數(shù)組里了

再看第二步, 核心的核心, 容器Container 來(lái)了, 這里不再贅述 依賴(lài)注入DI/控制反轉(zhuǎn)IoC 等基礎(chǔ)知識(shí), 不熟悉的小伙伴要去補(bǔ)補(bǔ)哦~

self::$container = new Container();
self::$container->setProperties($properties);
self::$container->autoloadServerAnnotation();

    /**
     * Register the annotation of server
     */
    public function autoloadServerAnnotation()
    {
        $bootScan = $this->getScanNamespaceFromProperties("bootScan"); // 獲取 property 配置中的 bootScan 配置項(xiàng)
        var_dump($bootScan);
        $resource = new ServerAnnotationResource($this->properties);
        $resource->addScanNamespace($bootScan); // 關(guān)鍵在這一句, 要掃描哪些命名空間(文件)
        $definitions = $resource->getDefinitions();
        var_dump($definitions);die;

        $this->definitions = array_merge($definitions, $this->definitions);
    }

重點(diǎn)來(lái)看看 $resource->addScanNamespace($bootScan)

注解的前半生: 要掃描哪些文件

$resource->addScanNamespace($bootScan) 繼承了抽象基類(lèi)繞了一下, 最后其實(shí)走到了這里

componentNamespaces[] = $ns;

            // console component
            if ($component == $this->consoleName) { // console 組件特殊處理
                $this->scanNamespaces[$ns] = $componentCommandDir;
                continue;
            }

            foreach ($this->serverScan as $dir) { // 預(yù)定義的命名空間
                $scanDir = $componentCommandDir . DS . $dir;
                if (!is_dir($scanDir)) {
                    continue;
                }

                $scanNs                        = $ns . "" . $dir;
                $this->scanNamespaces[$scanNs] = $scanDir;
            }
        }
    }
}

    /**
     * @var array
     */
    protected $serverScan
        = [
            "Command",
            "Bootstrap",
            "Aop",
        ];
// $this->scanNamespaces 的內(nèi)容示例
  ["SwoftWebSocketServerBootstrap"]=>
  string(65) "/var/www/swoole/swoft/vendor/swoft/websocket-server/src/Bootstrap"

恭喜你, 到這里你已經(jīng)理解了一半的注解功能:

swoft 框架是由一個(gè)一個(gè)功能組件組成, 詳細(xì)內(nèi)容可以移步 swoft框架組件化改造

默認(rèn)掃描注解包含 2 部分內(nèi)容:
config/propertiesbootScan 配置的命名空間
swoft所有組件下的 Command Bootstrap Aop 命名空間, 其中 console 組件特殊處理

如果到這里你感覺(jué)比較難理解, 你需要補(bǔ)充一下基礎(chǔ)知識(shí):

composer 基礎(chǔ)知識(shí): autoload 機(jī)制, 命名空間

swoft 組件相關(guān)知識(shí), 在 composer 基礎(chǔ)知識(shí)之上

另外, 上面加的測(cè)試代碼 var_dump(App::getAlias("@vendor/swoft"));, 可以思考一下 swoft 的別名機(jī)制就是為了解決 路徑問(wèn)題, 為什么這里又不用呢?

注解的后半生: 掃描出的結(jié)果

$definitions = $resource->getDefinitions(); 對(duì)應(yīng)的內(nèi)容:

    /**
     * 獲取已解析的配置beans
     *
     * @return array
     * 
     * [
     *     "beanName" => ObjectDefinition,
     *      ...
     * ]
     * 
*/ public function getDefinitions() { // 獲取掃描的PHP文件 $classNames = $this->registerLoaderAndScanBean(); // 掃描上一步注冊(cè)進(jìn)來(lái)的命名空間 $fileClassNames = $this->scanFilePhpClass(); // 額外配置的掃描文件, 大家可以嘗試一下在哪配置的哦 $classNames = array_merge($classNames, $fileClassNames); // 獲取到所有需要掃面的類(lèi) foreach ($classNames as $className) { $this->parseBeanAnnotations($className); // 解析bean注解 } $this->parseAnnotationsData(); // 解析注解數(shù)據(jù), 存放到 $this->definitions 中 return $this->definitions; // 最后, 我們使用這個(gè)就可以獲取到注解解析出來(lái)的了類(lèi)啦 }
// 看一看注解解析出來(lái)的例子
  ["SwoftWebSocketServerBootstrapCoreBean"]=>
  object(SwoftBeanObjectDefinition)#126 (7) {
    ["name":"SwoftBeanObjectDefinition":private]=>
    string(41) "SwoftWebSocketServerBootstrapCoreBean"
    ["className":"SwoftBeanObjectDefinition":private]=>
    string(41) "SwoftWebSocketServerBootstrapCoreBean"
    ["scope":"SwoftBeanObjectDefinition":private]=>
    int(1)
    ["ref":"SwoftBeanObjectDefinition":private]=>
    string(0) ""
    ["constructorInjection":"SwoftBeanObjectDefinition":private]=>
    NULL
    ["propertyInjections":"SwoftBeanObjectDefinition":private]=>
    array(0) {
    }
    ["methodInjections":"SwoftBeanObjectDefinition":private]=>
    array(0) {
    }
  }

這里隱藏了掃描不同類(lèi)型注解的細(xì)節(jié), 因?yàn)槲覀兒竺骈喿x不同組件源碼時(shí)會(huì)一一遇到, 這里只要理解大致原理即可

后面的 2 句比較簡(jiǎn)單:

$definition = self::getServerDefinition();
self::$container->addDefinitions($definition);

    /**
     * @return array
     * @throws InvalidArgumentException
     */
    private static function getServerDefinition(): array
    {
        $file             = App::getAlias("@console");
        $configDefinition = [];

        if (is_readable($file)) {
            $configDefinition = require_once $file;
        }

        $coreBeans  = self::getCoreBean(BootBeanCollector::TYPE_SERVER);
        var_dump($coreBeans);die;

        return ArrayHelper::merge($coreBeans, $configDefinition);
    }

簡(jiǎn)單打印一下就可以知道結(jié)果:

root@e38a7e5aff40 /v/w/s/swoft# php bin/swoft
array(1) {
  ["commandRoute"]=>
  array(1) {
    ["class"]=>
    string(35) "SwoftConsoleRouterHandlerMapping"
  }
}
大功告成: 初始化 Bean
self::$container->initBeans(); // 進(jìn)去查看

    /**
     * @throws InvalidArgumentException
     * @throws ReflectionException
     */
    public function initBeans()
    {
        $autoInitBeans = $this->properties["autoInitBean"] ?? false;
        if (!$autoInitBeans) {
            return;
        }

        // 循環(huán)初始化
        foreach ($this->definitions as $beanName => $definition) {
            $this->get($beanName);
        }
    }

    /**
     * 獲取一個(gè)bean
     *
     * @param string $name 名稱(chēng)
     *
     * @return mixed
     * @throws ReflectionException
     * @throws InvalidArgumentException
     */
    public function get(string $name)
    {
        // 已經(jīng)創(chuàng)建
        if (isset($this->singletonEntries[$name])) { // 單例, 初始化過(guò)就直接返回
            return $this->singletonEntries[$name];
        }

        // 未定義
        if (!isset($this->definitions[$name])) {
            throw new InvalidArgumentException(sprintf("Bean %s not exist", $name));
        }

        /* @var ObjectDefinition $objectDefinition */
        $objectDefinition = $this->definitions[$name];

        return $this->set($name, $objectDefinition); // 沒(méi)有初始化則進(jìn)行初始化
    }

    /**
     * 創(chuàng)建bean
     *
     * @param string           $name             名稱(chēng)
     * @param ObjectDefinition $objectDefinition bean定義
     *
     * @return object
     * @throws ReflectionException
     * @throws InvalidArgumentException
     */
    private function set(string $name, ObjectDefinition $objectDefinition)
    {
        // bean創(chuàng)建信息
        $scope             = $objectDefinition->getScope();
        $className         = $objectDefinition->getClassName();
        $propertyInjects   = $objectDefinition->getPropertyInjections();
        $constructorInject = $objectDefinition->getConstructorInjection();

        if ($refBeanName = $objectDefinition->getRef()) {
            return $this->get($refBeanName);
        }

        // 構(gòu)造函數(shù)
        $constructorParameters = [];
        if ($constructorInject !== null) {
            $constructorParameters = $this->injectConstructor($constructorInject);
        }

        $reflectionClass = new ReflectionClass($className);
        $properties      = $reflectionClass->getProperties();

        // new實(shí)例
        $isExeMethod = $reflectionClass->hasMethod($this->initMethod);
        $object      = $this->newBeanInstance($reflectionClass, $constructorParameters);

        // 屬性注入
        $this->injectProperties($object, $properties, $propertyInjects);

        // 執(zhí)行初始化方法
        if ($isExeMethod) {
            $object->{$this->initMethod}();
        }

        if (!$object instanceof AopInterface) {
            $object = $this->proxyBean($name, $className, $object);
        }

        // 單例處理
        if ($scope === Scope::SINGLETON) {
            $this->singletonEntries[$name] = $object;
        }

        return $object;

    }

Bean 初始化的所有細(xì)節(jié)都在這里了:

注解解析后獲取到的類(lèi)相關(guān)的所有信息

注入構(gòu)造函數(shù)(construct)

初始化類(lèi)(new), 此時(shí)會(huì)執(zhí)行構(gòu)造函數(shù)

注入屬性(property)

執(zhí)行初始化方法, 這就是為什么 Bean 里面定義的 init() 也會(huì)執(zhí)行的

AOP處理, 找到實(shí)際代理的類(lèi)

單例處理

返回生成好的 Bean 對(duì)象

到這里 整個(gè) swoft 核心中的核心 就已經(jīng)呈現(xiàn)在你面前了, 總結(jié)起來(lái)也很簡(jiǎn)單:

swoft啟動(dòng)時(shí)要去哪里掃描注解

swoft掃描到的注解如何初始化 Bean

有了 SwoftBeanBeanFactory::init(); 以后, 我們需要使用 Bean, 只需要:

SwoftBeanBeanFactory::getBean("xxx");

// 下面的寫(xiě)法只是一層封裝而已
SwoftApp::getBean("xxx");

    /**
     * get bean
     *
     * @param string $name 名稱(chēng)
     *
     * @return mixed
     */
    public static function getBean(string $name)
    {
        return ApplicationContext::getBean($name);
    }
bootstrap階段的最后: 各項(xiàng)配置

通過(guò)在合適的地方打印:

/* @var SwoftBootstrapBootsBootable $bootstrap*/
$bootstrap = SwoftApp::getBean(SwoftBootstrapBootstrap::class);
var_dump($bootstrap);
$bootstrap->bootstrap();

    /**
     * bootstrap
     */
    public function bootstrap()
    {
        $bootstraps = BootstrapCollector::getCollector(); // 需要執(zhí)行哪些 bootstrap
        var_dump($bootstraps);die;
        $temp = array_column($bootstraps, "order");

        array_multisort($temp, SORT_ASC, $bootstraps);

        foreach ($bootstraps as $bootstrapBeanName => $name){
            /* @var Bootable $bootstrap*/
            $bootstrap = App::getBean($bootstrapBeanName);
            $bootstrap->bootstrap();
        }
    }

結(jié)果如下:

root@e38a7e5aff40 /v/w/s/swoft# php bin/swoft
object(Bootstrap_5b6dd8716a6dc)#209 (1) {
  ["__handler_5b6dd8716a6dc":"Bootstrap_5b6dd8716a6dc":private]=>
  object(SwoftProxyHandlerAopHandler)#188 (1) { # 用到了 aop
    ["target":"SwoftProxyHandlerAopHandler":private]=>
    object(SwoftBootstrapBootstrap)#186 (0) {
    }
  }
}
array(3) { # 真正執(zhí)行的 bootstrap
  ["SwoftBootstrapBootsInitPhpEnv"]=> # init php env
  array(2) {
    ["name"]=>
    string(0) ""
    ["order"]=>
    int(2)
  }
  ["SwoftBootstrapBootsLoadEnv"]=> # 加載 .env 文件
  array(2) {
    ["name"]=>
    string(0) ""
    ["order"]=>
    int(1)
  }
  ["SwoftBootstrapBootsLoadInitConfiguration"]=> # 加載 config 目錄的其他配置
  array(2) {
    ["name"]=>
    string(0) ""
    ["order"]=>
    int(3)
  }
}

至此, bootstrap 階段的所有工作就完成了

swoft 中的 bean 到底是啥咧

回答 bean 是啥之前, 先記住: 一切皆對(duì)象

我們使用對(duì)面對(duì)象的方式來(lái)對(duì)問(wèn)題進(jìn)行抽象, 并使用抽象出來(lái)的類(lèi)實(shí)例化后的對(duì)象來(lái)解決問(wèn)題, 而實(shí)例化后的對(duì)象, 就是 swoft 中一個(gè)又一個(gè)的 Bean

回顧我們整個(gè) bootstrap 階段, 可以概括為自動(dòng)化做了 2 件事情:

根據(jù)默認(rèn)的注解掃描機(jī)制, 實(shí)例化 Bean

根據(jù) config/ .env 等配置中中的 bean/property, 對(duì) swoft 中的 Bean 進(jìn)行配置(實(shí)例化 Bean, 或者配置 Bean 的 property)

這樣通過(guò)配置來(lái)示例化類(lèi)和配置對(duì)象屬性的方式, 在 php 框架中大型其道, 典型的如 yii/laravel.

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/29200.html

相關(guān)文章

  • swoft| 源碼解讀系列一: 好難! swoft demo 都跑不起來(lái)怎么破? docker 了解

    摘要:源碼解讀系列一好難都跑不起來(lái)怎么破了解一下唄閱讀框架源碼第一步搞定環(huán)境小伙伴剛接觸的時(shí)候會(huì)感覺(jué)壓力有點(diǎn)大更直觀的說(shuō)法是難開(kāi)發(fā)組是不贊成難這個(gè)說(shuō)法的的代碼都是實(shí)現(xiàn)的而又是世界上最好的語(yǔ)言的代碼閱讀起來(lái)是很輕松的開(kāi)發(fā)組會(huì)用源碼解讀系列博客深 date: 2018-8-01 14:22:17title: swoft| 源碼解讀系列一: 好難! swoft demo 都跑不起來(lái)怎么破? doc...

    shenhualong 評(píng)論0 收藏0
  • swoft| 源碼解讀系列一: 好難! swoft demo 都跑不起來(lái)怎么破? docker 了解

    摘要:源碼解讀系列一好難都跑不起來(lái)怎么破了解一下唄閱讀框架源碼第一步搞定環(huán)境小伙伴剛接觸的時(shí)候會(huì)感覺(jué)壓力有點(diǎn)大更直觀的說(shuō)法是難開(kāi)發(fā)組是不贊成難這個(gè)說(shuō)法的的代碼都是實(shí)現(xiàn)的而又是世界上最好的語(yǔ)言的代碼閱讀起來(lái)是很輕松的開(kāi)發(fā)組會(huì)用源碼解讀系列博客深 date: 2018-8-01 14:22:17title: swoft| 源碼解讀系列一: 好難! swoft demo 都跑不起來(lái)怎么破? doc...

    rollback 評(píng)論0 收藏0
  • Swoft 源碼剖析 - Swoole和Swoft的那些事 (Http/Rpc服務(wù)篇)

    摘要:和服務(wù)關(guān)系最密切的進(jìn)程是中的進(jìn)程組,絕大部分業(yè)務(wù)處理都在該進(jìn)程中進(jìn)行。隨后觸發(fā)一個(gè)事件各組件通過(guò)該事件進(jìn)行配置文件加載路由注冊(cè)。事件每個(gè)請(qǐng)求到來(lái)時(shí)僅僅會(huì)觸發(fā)事件。服務(wù)器生命周期和服務(wù)基本一致,詳情參考源碼剖析功能實(shí)現(xiàn) 作者:bromine鏈接:https://www.jianshu.com/p/4c0...來(lái)源:簡(jiǎn)書(shū)著作權(quán)歸作者所有,本文已獲得作者授權(quán)轉(zhuǎn)載,并對(duì)原文進(jìn)行了重新的排版。S...

    張漢慶 評(píng)論0 收藏0
  • Swoft 新手向教程 - 通過(guò) Docker 搭建一個(gè)開(kāi)發(fā)環(huán)境

    摘要:前言是一個(gè)在之上構(gòu)建的一個(gè)高性能協(xié)程全棧框架,而在里面是一個(gè)高級(jí)技能,所以在相關(guān)的環(huán)境安裝上也給許多人造成了很大的困擾,更是如此,本文將通過(guò)以一種極其簡(jiǎn)單的方式解決運(yùn)行環(huán)境和開(kāi)發(fā)環(huán)境的部署。 showImg(https://segmentfault.com/img/bVbeknK?w=512&h=197); 本系列文章將從使用層面介紹 Swoft 框架的使用及業(yè)務(wù)開(kāi)發(fā),面向初中級(jí)的 P...

    tinysun1234 評(píng)論0 收藏0
  • 阿里小哥帶你玩轉(zhuǎn)JVM:揭秘try-catch-finally在JVM底層都干些啥

    摘要:當(dāng)觸發(fā)異常的字節(jié)碼的索引值在某個(gè)異常表?xiàng)l目的監(jiān)控范圍內(nèi),虛擬機(jī)會(huì)判斷所拋出的異常和該條目想要捕獲的異常是否匹配。 作者:李瑞杰目前就職于阿里巴巴,狂熱JVM愛(ài)好者讓我們準(zhǔn)備一個(gè)函數(shù):showImg(https://user-gold-cdn.xitu.io/2019/5/19/16acbce35adfefb7);然后,反編譯他的字節(jié)碼:showImg(https://user-gold-cd...

    番茄西紅柿 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

hqman

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<