從山丘錘王之死談Spring AOP中的引介(Introduction)
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 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級山丘之王