引介(Introduction)是指在不更改源代碼的情況,給一個現有類增加屬性、方法,以及讓現有類實現其它接口或指定其它父類等,從而改變類的靜態結構。Spring AOP通過采代理加攔截器的方式來實現的,可以通過攔截器機制使一個實有類實現指定的接口。
            在實際應用中可以使用DefaultIntroductionAdvisor來配置引介,也可以直接繼承 DefaultIntroductionAdvisor來實現引介。這里是昨天在《深入Spring 2:輕量級J2EE開發框架原理與實踐》中作的一個示例。總體感覺代理攔截機制實現的引介,達到類似于AspectJ那樣的語言擴展方式實現的AOP引介的火力還差很多。
            示例是一個模擬Warcraft的小游戲,包括英雄、道具、技能、戰場(地圖)等。整個示例UML圖如下所示:
            
            
            示例中的英雄、地圖及各自持有的道具等全部通過在Spring配置文件中設置。下面是配置文件中英雄及戰場的部分:
          <!--10級角色引介-->
          <bean id="superHeroIntroduction"
          ??class="springroad.demo.chap5.wow.SuperHeroIntroductionAdvisor" />
          ?
            <!--代理配置模板-->
          ?<bean id="baseHeroProxy"
          ??class="org.springframework.aop.framework.ProxyFactoryBean"
          ??abstract="true">
          ??<property name="proxyInterfaces"
          ???value="springroad.demo.chap5.wow.Hero" />
          ??<property name="interceptorNames">
          ???<list>
          ????<value>gameRecordAspect</value>
          ????<value>armorAspect</value>????
          ???</list>
          ??</property>
          ?</bean>
          ?<!--定義英雄-->
          ?<bean id="MK" parent="baseHeroProxy">
          ??<property name="target">
          ???<bean class="springroad.demo.chap5.wow.BaseHero">
          ????<constructor-arg value="60" />
          ????<property name="armor" value="2" />
          ????<property name="health" value="500" />
          ????<property name="name" value="Mountain King" />
          ????<property name="auraAndSkill">
          ?????<list>
          ??????<ref bean="bash" />
          ??????<ref bean="scrollOfProtection" />
          ?????</list>
          ????</property>
          ???</bean>
          ??</property>
          ?</bean>
          ?<bean id="POM" parent="baseHeroProxy">
          ??<property name="target">
          ???<bean class="springroad.demo.chap5.wow.BaseHero">
          ????<constructor-arg value="60" />
          ????<property name="armor" value="1" />
          ????<property name="health" value="500" />
          ????<property name="name" value="Priestess of the Moon" />
          ????<property name="auraAndSkill">
          ?????<list>
          ??????<ref bean="devotionAura" />
          ??????<ref bean="scrollOftheBeast" />
          ??????<ref bean="trueshotAura" />
          ?????</list>
          ????</property>
          ???</bean>
          ??</property>
          ?</bean>
          ?<bean id="superHero" parent="baseHeroProxy">
          ??<property name="target">
          ???<bean class="springroad.demo.chap5.wow.BaseHero">
          ????<constructor-arg value="60" />
          ????<property name="armor" value="1" />
          ????<property name="health" value="500" />
          ????<property name="name" value="10級山丘之王" />
          ????<property name="auraAndSkill">
          ?????<list>
          ??????<ref bean="bash" />
          ??????<ref bean="devotionAura" />
          ??????<ref bean="scrollOftheBeast" />
          ??????<ref bean="trueshotAura" />
          ?????</list>
          ????</property>
          ???</bean>
          ??</property>
          ??<property name="interceptorNames">
          ???<list>
          ????<value>gameRecordAspect</value>
          ????<value>armorAspect</value>???
          ????<value>superHeroIntroduction</value>
          ???</list>
          ??</property>
          ?</bean>
          ?<bean id="WarField"
          ??class="org.springframework.aop.framework.ProxyFactoryBean">
          ??<property name="target">
          ???<bean class="springroad.demo.chap5.wow.WarField">
          ????<property name="heros">
          ?????<set>
          ??????<ref bean="MK" />
          ??????<ref bean="POM" />
          ??????<ref bean="superHero" />
          ?????</set>
          ????</property>
          ???</bean>
          ??</property>
          ??<property name="interceptorNames">
          ???<list>
          ????<value>warAspect</value>
          ???</list>
          ??</property>
          ?</bean> 
          ?
            通過配置可以看出,通過使用引介讓superHero(也即10級山丘之王)實現了SuperHero接口,這樣使得概率出招成功的技能具有100%的出招成功率。
            比如,下面是重擊技能的代碼:
            
          import java.util.Random;
          //重擊技能,具有20%的概率,可以增加英雄的攻擊力20點,如果角色變為SuperHero,則重擊100%成功
          public class Bash implements AttackProp {
          ?private boolean haveHit;
          ?private Random random = new Random();
          ?public int getAttack(Hero hero) {
          ??if (bigHit() || (hero instanceof SuperHero)) {
          ???haveHit = true;
          ??} else {
          ???haveHit = false;
          ??}
          ??return (haveHit ? 20 : 0);
          ?}
          ?public boolean bigHit() {
          ??int rat = random.nextInt(10);
          ?//?System.out.println(rat);
          ??return (rat <= 2);
          ?}
          ?public String toString() {
          ??return "重擊技能," + (haveHit ? "傷害提高了20點" : "未使出來");
          ?}
          }
            通過代碼可以看出來,如果英雄是SuperHero(即10級角色),則出招成功率100%,否則只有20%多。SuperHero只是一個標識接口,內容如下:
            public interface SuperHero {
            }
          ?
            我們重點看看SuperHeroIntroductionAdvisor,這個引介就是讓某一個現有的對象實現指定接口。代碼如下示:
          import org.springframework.aop.support.DefaultIntroductionAdvisor;
          import org.springframework.aop.support.DelegatingIntroductionInterceptor;
          public class SuperHeroIntroductionAdvisor extends DefaultIntroductionAdvisor {
          ?public SuperHeroIntroductionAdvisor() {
          ??super(new DelegatingIntroductionInterceptor(new SuperHero(){}), SuperHero.class);
          ?}
          }
            現在我們來討Spring AOP中引介的問題。假如我們的程序需要在Hero上有一個增強,然后通過Hero的實現BaseHero自身來發出技能,也即在BaseHero中包含調用Bash的代碼,則該引介將會失效。這是因為當Hero自身調用的時候,已經不再是通過代理對象調用,而是通過目標對象Hero本身來調用,所有代理攔截都將失效,包括引介。
          ?
            假如你是在Hero之外的另外一個攔截中來調用Bash,也就是說想讓一個引介外的攔截跟引介混合使用,則引介同樣失效。由于引介的失效,所以造成Bash認不出來SuperHero角色,這就是為什么10級山丘之王的重擊技能不能100%發出的原因。
          ?
            代理攔截引介實際上是代理類實現指定接口,并沒有改變實際的類,比如不會因為superHero引入了SuperHero接口而對其它的Hero造成影響。另外注意的是,Spring AOP中的引介不能和任何切入點一起使用,因為它是應用在類級別而不是方法級別。
          ?
            確保是在代理對象上調用引介模塊,而不是在目標對象。下面是修正后的山丘之王的作戰記錄:
          ?
          log4j:WARN No appenders could be found for logger (org.springframework.core.CollectionFactory).
          log4j:WARN Please initialize the log4j system properly.
          [英雄名稱:Mountain King,生命值:500,基本防御:2]
          [英雄名稱:Priestess of the Moon,生命值:500,基本防御:1]
          [英雄名稱:10級山丘之王,生命值:500,基本防御:1]
          戰斗開始......
          第1回合:玩家[Mountain King]向[Priestess of the Moon]發動攻擊![命中:失敗]
          第2回合:玩家[Priestess of the Moon]向[Mountain King]發動攻擊![命中:成功]
          生命值--[Priestess of the Moon:500]-[Mountain King:500]
          基本傷害:60;英雄持有以下攻擊道具:物品野獸卷軸,攻擊增加了25%;強擊光環技能,攻擊力增加了10%;[實際攻攻擊力:81]
          Mountain King--基本護甲:2;物品保護卷軸,護甲增加了2點;[實際防御:4]
          實際傷害點數:77
          第3回合:玩家[10級山丘之王]向[Mountain King]發動攻擊![命中:成功]
          生命值--[10級山丘之王:500]-[Mountain King:423]
          基本傷害:60;英雄持有以下攻擊道具:重擊技能,傷害提高了20點;物品野獸卷軸,攻擊增加了25%;強擊光環技能,攻擊力增加了10%;[實際攻攻擊力:101]
          Mountain King--基本護甲:2;物品保護卷軸,護甲增加了2點;[實際防御:4]
          實際傷害點數:97
          第4回合:玩家[Mountain King]向[10級山丘之王]發動攻擊![命中:成功]
          生命值--[Mountain King:326]-[10級山丘之王:500]
          基本傷害:60;英雄持有以下攻擊道具:重擊技能,傷害提高了20點;[實際攻攻擊力:80]
          10級山丘之王--基本護甲:1;專注光環技能,護甲增加了1點!;[實際防御:2]
          實際傷害點數:78
          第5回合:玩家[Priestess of the Moon]向[10級山丘之王]發動攻擊![命中:失敗]
          第6回合:玩家[10級山丘之王]向[Mountain King]發動攻擊![命中:失敗]
          第7回合:玩家[Mountain King]向[Priestess of the Moon]發動攻擊![命中:成功]
          生命值--[Mountain King:326]-[Priestess of the Moon:500]
          基本傷害:60;英雄持有以下攻擊道具:重擊技能,未使出來;[實際攻攻擊力:60]
          Priestess of the Moon--基本護甲:1;專注光環技能,護甲增加了1點!;[實際防御:2]
          實際傷害點數:58
          第8回合:玩家[Priestess of the Moon]向[Mountain King]發動攻擊![命中:失敗]
          第9回合:玩家[10級山丘之王]向[Mountain King]發動攻擊![命中:成功]
          生命值--[10級山丘之王:422]-[Mountain King:326]
          基本傷害:60;英雄持有以下攻擊道具:重擊技能,傷害提高了20點;物品野獸卷軸,攻擊增加了25%;強擊光環技能,攻擊力增加了10%;[實際攻攻擊力:101]
          Mountain King--基本護甲:2;物品保護卷軸,護甲增加了2點;[實際防御:4]
          實際傷害點數:97
          第10回合:玩家[Mountain King]向[Priestess of the Moon]發動攻擊![命中:失敗]
          第11回合:玩家[Priestess of the Moon]向[Mountain King]發動攻擊![命中:成功]
          生命值--[Priestess of the Moon:442]-[Mountain King:229]
          基本傷害:60;英雄持有以下攻擊道具:物品野獸卷軸,攻擊增加了25%;強擊光環技能,攻擊力增加了10%;[實際攻攻擊力:81]
          Mountain King--基本護甲:2;物品保護卷軸,護甲增加了2點;[實際防御:4]
          實際傷害點數:77
          第12回合:玩家[10級山丘之王]向[Priestess of the Moon]發動攻擊![命中:成功]
          生命值--[10級山丘之王:422]-[Priestess of the Moon:442]
          基本傷害:60;英雄持有以下攻擊道具:重擊技能,傷害提高了20點;物品野獸卷軸,攻擊增加了25%;強擊光環技能,攻擊力增加了10%;[實際攻攻擊力:101]
          Priestess of the Moon--基本護甲:1;專注光環技能,護甲增加了1點!;[實際防御:2]
          實際傷害點數:99
          第13回合:玩家[Mountain King]向[Priestess of the Moon]發動攻擊![命中:成功]
          生命值--[Mountain King:152]-[Priestess of the Moon:343]
          基本傷害:60;英雄持有以下攻擊道具:重擊技能,未使出來;[實際攻攻擊力:60]
          Priestess of the Moon--基本護甲:1;專注光環技能,護甲增加了1點!;[實際防御:2]
          實際傷害點數:58
          第14回合:玩家[Priestess of the Moon]向[10級山丘之王]發動攻擊![命中:成功]
          生命值--[Priestess of the Moon:285]-[10級山丘之王:422]
          基本傷害:60;英雄持有以下攻擊道具:物品野獸卷軸,攻擊增加了25%;強擊光環技能,攻擊力增加了10%;[實際攻攻擊力:81]
          10級山丘之王--基本護甲:1;專注光環技能,護甲增加了1點!;[實際防御:2]
          實際傷害點數:79
          第15回合:玩家[10級山丘之王]向[Priestess of the Moon]發動攻擊![命中:成功]
          生命值--[10級山丘之王:343]-[Priestess of the Moon:285]
          基本傷害:60;英雄持有以下攻擊道具:重擊技能,傷害提高了20點;物品野獸卷軸,攻擊增加了25%;強擊光環技能,攻擊力增加了10%;[實際攻攻擊力:101]
          Priestess of the Moon--基本護甲:1;專注光環技能,護甲增加了1點!;[實際防御:2]
          實際傷害點數:99
          第16回合:玩家[Mountain King]向[10級山丘之王]發動攻擊![命中:失敗]
          第17回合:玩家[Priestess of the Moon]向[10級山丘之王]發動攻擊![命中:成功]
          生命值--[Priestess of the Moon:186]-[10級山丘之王:343]
          基本傷害:60;英雄持有以下攻擊道具:物品野獸卷軸,攻擊增加了25%;強擊光環技能,攻擊力增加了10%;[實際攻攻擊力:81]
          10級山丘之王--基本護甲:1;專注光環技能,護甲增加了1點!;[實際防御:2]
          實際傷害點數:79
          第18回合:玩家[10級山丘之王]向[Mountain King]發動攻擊![命中:失敗]
          第19回合:玩家[Mountain King]向[Priestess of the Moon]發動攻擊![命中:成功]
          生命值--[Mountain King:152]-[Priestess of the Moon:186]
          基本傷害:60;英雄持有以下攻擊道具:重擊技能,傷害提高了20點;[實際攻攻擊力:80]
          Priestess of the Moon--基本護甲:1;專注光環技能,護甲增加了1點!;[實際防御:2]
          實際傷害點數:78
          第20回合:玩家[Priestess of the Moon]向[Mountain King]發動攻擊![命中:失敗]
          第21回合:玩家[10級山丘之王]向[Mountain King]發動攻擊![命中:成功]
          生命值--[10級山丘之王:264]-[Mountain King:152]
          基本傷害:60;英雄持有以下攻擊道具:重擊技能,傷害提高了20點;物品野獸卷軸,攻擊增加了25%;強擊光環技能,攻擊力增加了10%;[實際攻攻擊力:101]
          Mountain King--基本護甲:2;物品保護卷軸,護甲增加了2點;[實際防御:4]
          實際傷害點數:97
          第22回合:玩家[Mountain King]向[Priestess of the Moon]發動攻擊![命中:成功]
          生命值--[Mountain King:55]-[Priestess of the Moon:108]
          基本傷害:60;英雄持有以下攻擊道具:重擊技能,傷害提高了20點;[實際攻攻擊力:80]
          Priestess of the Moon--基本護甲:1;專注光環技能,護甲增加了1點!;[實際防御:2]
          實際傷害點數:78
          第23回合:玩家[Priestess of the Moon]向[Mountain King]發動攻擊![命中:成功]
          生命值--[Priestess of the Moon:30]-[Mountain King:55]
          基本傷害:60;英雄持有以下攻擊道具:物品野獸卷軸,攻擊增加了25%;強擊光環技能,攻擊力增加了10%;[實際攻攻擊力:81]
          Mountain King--基本護甲:2;物品保護卷軸,護甲增加了2點;[實際防御:4]
          實際傷害點數:77
          英雄 Mountain King 掛了
          第24回合:玩家[10級山丘之王]向[Priestess of the Moon]發動攻擊![命中:成功]
          生命值--[10級山丘之王:264]-[Priestess of the Moon:30]
          基本傷害:60;英雄持有以下攻擊道具:重擊技能,傷害提高了20點;物品野獸卷軸,攻擊增加了25%;強擊光環技能,攻擊力增加了10%;[實際攻攻擊力:101]
          Priestess of the Moon--基本護甲:1;專注光環技能,護甲增加了1點!;[實際防御:2]
          實際傷害點數:99
          英雄 Priestess of the Moon 掛了

          最終勝利者:10級山丘之王

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           

          posts - 51, comments - 17, trackbacks - 0, articles - 0

          Copyright © 笨蛋啊帆

          主站蜘蛛池模板: 昂仁县| 邮箱| 萨迦县| 吉木萨尔县| 特克斯县| 永定县| 平利县| 镇江市| 宁津县| 吴川市| 贞丰县| 称多县| 麻江县| 永顺县| 桂东县| 赤壁市| 江山市| 行唐县| 彰化市| 罗山县| 东丽区| 鄄城县| 亚东县| 子洲县| 大丰市| 辉南县| 怀化市| 乾安县| 衢州市| 万安县| 湖北省| 同仁县| 工布江达县| 乐都县| 毕节市| 上饶县| 延寿县| 白朗县| 韶山市| 图木舒克市| 罗甸县|