反射機制與動態(tài)代理

優(yōu)點
可以這么說侣滩,反射完整的描述了一個類或者對象的原型,
它可以用作文檔生成口注,所以,我們可以用它對文檔中的類進行掃描君珠,逐個生成掃描文檔寝志。
反射可以探知類的內(nèi)部結(jié)構(gòu)
也可以用作hook來實現(xiàn)插件功能,還有就是可以做動態(tài)代理
缺點
反射的消耗也是不小的策添,我們在有另外一種方案的時候材部,盡量不要選擇反射。
很多時候唯竹,善用某個東西乐导,會使得我們的代碼,簡潔又優(yōu)雅浸颓,但是不能貪多物臂,比如這個反射API旺拉,用的多了,會破壞我們類的封裝性棵磷,使得本不應(yīng)該暴露的方法暴露了出來蛾狗,這是優(yōu)點也是缺點

反射類 可得到的信息
ReflectionObject 對象信息
ReflectionFunction() 函數(shù)定義所在的文件以及起始位置
ReflectionClass() 常量、屬性仪媒、方法沉桌、命名空間、類是否為final或abstract等
ReflectionMethod() 方法修飾類型规丽、方法名蒲牧、方法注釋等

反射機制的應(yīng)用
動態(tài)代理:也叫委托請求,在委托模式中赌莺,有兩個對象參與處理同一個請求冰抢,接受請求的對象將請求委托給另一個對象來處理
插件系統(tǒng):利用反射機制自動獲取插件列表以及其他相關(guān)信息

/**
 * 類A
 * zeng
 */
class A 
{
    public function t1() {
         echo '我是一個不帶參數(shù)的方法<br>';
    }

    public function t2($str) {
          echo "我是一個帶參數(shù)的方法t2,參數(shù)是:" .$str,'<br>';
    }

    private function t3() {

    }

    static function t4() {
        echo '我是一個靜態(tài)方法';
    }
}
$a = new A();
$ref_cls = new ReflectionClass('A');
$ref_method = $ref_cls->getMethod('t1');// 相當于new ReflectionMethod('A','t1')

//var_dump($ref_cls->hasMethod('t1'));//true
//var_dump($ref_method->isPublic());//true

//執(zhí)行方法
//靜態(tài)方法調(diào)用 invoke(null,參數(shù))
//普通方法調(diào)用 invoke(實例對象,參數(shù))
//私有方法不能用invoke調(diào)用
if( $ref_method->isPublic() && !$ref_method->isAbstract() )
{
    if( $ref_method->isStatic() )
    {
        $ref_method->invoke(null);
    } 
    else
    {
        $ref_method->invoke($a);//$a可以換成$ref_cls->newInstance();
    }
}

/*
 * isPublic
 * isPrivate
 * ....
 * */
//$ref_cls_all_method = $ref_cls->getMethods();
//echo '<pre>';
//print_r($ref_cls_all_method);
/*
Array
(
    [0] => ReflectionMethod Object
        (
            [name] => t1
            [class] => A
        )

    [1] => ReflectionMethod Object
        (
            [name] => t2
            [class] => A
        )

    [2] => ReflectionMethod Object
        (
            [name] => t3
            [class] => A
        )

    [3] => ReflectionMethod Object
        (
            [name] => t4
            [class] => A
        )
)
 */
class A
{
    function showInfo() {
        echo 'Class A showinfo';
    }
}

class B
{
    private $obj;

    function __construct() {
        $this->obj = new A();
    }

    /*function addObj($obj) {
         $this->obj[] = $obj;
    }*/

    function __call($name,$args) {
        $ref_cls = new ReflectionClass($this->obj);

        if($ref_cls->hasMethod($name))
        {
            $ref_method = $ref_cls->getMethod($name);

            if( $ref_method->isPublic() && !$ref_method->isAbstract() )
            {
                if( $ref_method->isStatic() )
                {
                    $ref_method->invoke(null);
                } 
                else
                {
                    $ref_method->invoke($this->obj);
                }
            }

        }
    }


}

$b = new B();

$b->showInfo();
Plugin.php
interface Plugin 
{
    function showMenu();
}

class MyPlugin implements Plugin
{
    function showMenu() {
        $menu = [
             [
                'name' => 'menu1',
                'link' => 'index.php?id=1'
             ],
             [
                'name' => 'menu2',
                'link' => 'index.php?id=2'
             ],
             [
                'name' => 'menu3',
                'link' => 'index.php?id=3'
             ]
        ];
        return $menu;
    }
}

class HisPlugin implements Plugin
{
    function showMenu() {
        $menu = [
             [
                'name' => 'menu4',
                'link' => 'index.php?id=4'
             ],
             [
                'name' => 'menu5',
                'link' => 'index.php?id=5'
             ],
             [
                'name' => 'menu6',
                'link' => 'index.php?id=6'
             ]
        ];
        return $menu;
    }
}

------------------------------------------
demo.php
include __DIR__ . '/Plugin.php';

function get_plugin_menus() {
    $all_class = get_declared_classes();
    $menus = $menu = [];
    foreach ($all_class as $cls) {
        $ref_cls = new ReflectionClass($cls);
        //判斷這個類是否實現(xiàn)了某個接口
        if($ref_cls->implementsInterface('Plugin')) {
            //echo $cls; //MyPlugin HisPlugin
            if($ref_cls->hasMethod('showMenu')){
                $ref_method = $ref_cls->getMethod('showMenu');
                if( $ref_method->isPublic() && !$ref_method->isAbstract() )
                {
                    if( $ref_method->isStatic() )
                    {
                        $menu = $ref_method->invoke(null);
                    }
                    else
                    {
                        //$ref_method->invoke(new $cls());
                        //通過反射類獲取類的一個實例
                        $instance = $ref_cls->newInstance();
                        $menu = $ref_method->invoke($instance);
                    }
                }
                $menus = array_merge($menus,$menu);
            }
        }
    }

    return $menus;
}

$menu = get_plugin_menus();
echo '<pre>';
print_r($menu);
/*
 Array
(
    [0] => Array
        (
            [name] => menu1
            [link] => index.php?id=1
        )

    [1] => Array
        (
            [name] => menu2
            [link] => index.php?id=2
        )

    [2] => Array
        (
            [name] => menu3
            [link] => index.php?id=3
        )

    [3] => Array
        (
            [name] => menu4
            [link] => index.php?id=4
        )

    [4] => Array
        (
            [name] => menu5
            [link] => index.php?id=5
        )

    [5] => Array
        (
            [name] => menu6
            [link] => index.php?id=6
        )

)
  */
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末艘狭,一起剝皮案震驚了整個濱河市挎扰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌巢音,老刑警劉巖遵倦,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異官撼,居然都是意外死亡梧躺,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門傲绣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來掠哥,“玉大人,你說我怎么就攤上這事秃诵⌒螅” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵菠净,是天一觀的道長禁舷。 經(jīng)常有香客問我病往,道長震蒋,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任萄金,我火速辦了婚禮攀唯,結(jié)果婚禮上霜大,老公的妹妹穿的比我還像新娘。我一直安慰自己革答,他們只是感情好战坤,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著残拐,像睡著了一般途茫。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上溪食,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天囊卜,我揣著相機與錄音,去河邊找鬼错沃。 笑死栅组,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的枢析。 我是一名探鬼主播玉掸,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼醒叁!你這毒婦竟也來了司浪?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤把沼,失蹤者是張志新(化名)和其女友劉穎啊易,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體饮睬,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡租谈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了捆愁。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片割去。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖牙瓢,靈堂內(nèi)的尸體忽然破棺而出劫拗,到底是詐尸還是另有隱情,我是刑警寧澤矾克,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布页慷,位于F島的核電站,受9級特大地震影響胁附,放射性物質(zhì)發(fā)生泄漏酒繁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一控妻、第九天 我趴在偏房一處隱蔽的房頂上張望州袒。 院中可真熱鬧,春花似錦弓候、人聲如沸郎哭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽夸研。三九已至邦蜜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間亥至,已是汗流浹背悼沈。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留姐扮,地道東北人絮供。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像茶敏,于是被迫代替她去往敵國和親壤靶。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理睡榆,服務(wù)發(fā)現(xiàn)萍肆,斷路器,智...
    卡卡羅2017閱讀 134,654評論 18 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法胀屿,類相關(guān)的語法塘揣,內(nèi)部類的語法,繼承相關(guān)的語法宿崭,異常的語法亲铡,線程的語...
    子非魚_t_閱讀 31,625評論 18 399
  • 1 凌晨12點35分,六年前的餛飩攤還在街角葡兑。 燈光昏黃奖蔓,一對夫妻并肩站在攤鋪前,丈夫下著餛飩讹堤,妻子在一旁揉著生面...
    周小凡閱讀 2,695評論 15 58
  • 從淘寶網(wǎng)上比選了許久吆鹤,選出了2套水溶彩鉛、紙洲守、筆終于到了疑务。為了能夠讓自己堅持下去,再選擇鉛筆時賣了一套小貴的鉛筆梗醇,...
    x123閱讀 200評論 0 0
  • 上班路上叙谨,聽何老師的課温鸽,第四周的課昨天聽了兩節(jié),挺起老有點累手负,也沒有什么觸動涤垫。今早順序聽第三節(jié)姑尺,看題目不是很感興趣...
    mw568閱讀 471評論 1 0