Spring是一個開源框架鼠渺,Spring根本使命:簡化Java開發(fā)。
為了簡化java開發(fā)的復雜性恨旱,Spring使用如下4種策略:
1座慰、基于POJO(Plain Old Java Object? 簡單Java對象 )的輕量級和最小侵入性編程。
2械荷、通過依賴注入和面向接口實現(xiàn)松耦合共耍。
3、基于切面和慣例進行聲明式編程吨瞎。
4痹兜、通過切面和模板減少樣板式代碼。
這里以一個騎士出征的例子來解釋一些相關(guān)概念
首先定義一個騎士接口颤诀,其中有一個embarkOnQuest方法字旭。
package hoo.knights;
public interface Knight {
? ? void embarkOnQuest();
}
然后再定義一個遠征行動接口。
package hoo.knights;
public interface Quest {
void embark();
}
下一步定義一個拯救少女行動類
package hoo.knights;
public class RescueDamselQuest implements Quest{
@Override
? ? public void embark() {
?????System.out.println("Embarking on a quest to rescue the damsel");
}
}
再定義一個屠殺巨龍行動類
package hoo.knights;
import java.io.PrintStream;
public class SlayDragonQuest implements Quest{
private PrintStreamprintStream;
? ? public SlayDragonQuest(PrintStream printStream){
this.printStream = printStream;
}
@Override
? ? public void embark() {
printStream.println("Embarking on quest to slay the dragon");
}
}
接下來定義一個英勇的騎士類實現(xiàn)騎士接口
package hoo.knights;
public class BraveKnight implements Knight{
private Questquest;
? ? public BraveKnight(Quest quest){
this.quest = quest;
}
@Override
? ? public void embarkOnQuest() {
quest.embark();
}
}
到這里可能就有人將BraveKnight類寫成:
package hoo.knights;
public class BraveKnight implements Knight{
private Questquest;
? ? public BraveKnight(){
quest = new?RescueDamselQuest ();
}
@Override
? ? public void embarkOnQuest() {
quest.embark();
}
}
但是有一種情況:騎士不僅僅可以去殺龍還可以去拯救少女這里將它寫死就不太合適崖叫,采用傳遞一個Quest對象遗淳,只要實現(xiàn)了Quest類的接口,任何類都可以傳進來心傀,騎士就可以去做很多行動屈暗,不是只執(zhí)行一個任務。
這是依賴注入(DI)的一種方式:構(gòu)造器注入
同樣SlayDragonQuest類中也有依賴注入:將一個PrintStream對象注入到SlayDragonQuest中。
騎士出征之前和之后需要法師的吟唱养叛,騎士類擁有法師類對象似乎不是一個好的選擇种呐,法師不應該被騎士擁有,有的騎士也不想法師吟唱這里先定義一個法師類一铅。
package hoo.knights;
import java.io.PrintStream;
public class Minstrel {
private PrintStream printStream;
public Minstrel(PrintStream printStream){
this.printStream = printStream;
}
public void singBeforeQuest(){
printStream.println("Fa la la,the knight is so brave!");
}
public void singAfterQuest(){
printStream.println("Tee hee hee , the brave knight did embark on a quest");
}
}
法師的吟唱是騎士的出征非關(guān)鍵因素陕贮,這里利用AOP來實現(xiàn)法師吟唱模塊化。
有多個Quest對象可以被注入到BraveKnight中潘飘,到底選擇哪一個來注入呢肮之??
這里利用XML來正確裝配這些對象卜录。
裝配的方式有:自動裝配戈擒、XML顯式裝配、Java顯式裝配艰毒。
先定義knight.xml來解決騎士到底要做什么的問題筐高。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
? ? ? xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
? ? ? xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="knight" class="hoo.knights.BraveKnight">
<constructor-arg ref="quest"/>
</bean>
<bean id="quest" class="hoo.knights.SlayDragonQuest">
<constructor-arg value="#{T(System).out}"/>
</bean>
</beans>
使用<bean></bean>聲明一個bean 其中id為自己指定的名字 class為bean的類
<constructor-arg> 元素為構(gòu)造器參數(shù) ref為依賴的bean,第一個constructor元素就決定了將一個id為quest的bean注入到id為knight的對象中丑瞧。第二個constructor元素中 value代表將一個System.out值傳入構(gòu)造器柑土。
第一個constructor元素就決定了騎士去殺龍而不是拯救少女。
等等绊汹,法師吟唱在哪稽屏??西乖?
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
? ? ? xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
? ? ? xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="knight" class="hoo.knights.BraveKnight">
<constructor-arg ref="quest"/>
</bean>
<bean id="quest" class="hoo.knights.SlayDragonQuest">
<constructor-arg value="#{T(System).out}"/>
</bean>
<bean id="minstrel" class="hoo.knights.Minstrel">
<constructor-arg value="#{T(System).out}"/>
</bean>
<aop:config>
<aop:aspect ref="minstrel">
<aop:pointcut id="embark" expression="execution(* *.embarkOnQuest(..))"/>
<aop:before pointcut-ref="embark" method="singBeforeQuest"/>
<aop:after pointcut-ref="embark" method="singAfterQuest"/>
</aop:aspect>
</aop:config>
</beans>
<aop:aspect ref="minstrel">這一句將法師類聲明為一個切面(AOP)狐榔。
pointcut定義了一個切入點,before決定在切入點之前做什么获雕,after決定在切入點之后做什么薄腻。
來到驗證階段,看看騎士到底干了啥事届案?
package hoo.knights;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class KnightMain {
public static void main(String[] args)throws Exception{
ClassPathXmlApplicationContext context =new ClassPathXmlApplicationContext("minstrel.xml");
//ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("knight.xml");
? ? ? ? Knight knight = context.getBean(Knight.class);
knight.embarkOnQuest();
context.close();
}
}
ClassPathXmlApplicationContext 從xml文件中讀取bean裝配信息庵楷,這玩意叫應用上下文。楣颠。
第一個決定了法師要出來吟唱嫁乘,通過控制臺可以看到法師出來吟唱了,并且騎士執(zhí)行的是殺龍的行動球碉。
注釋的第二行決定法師不出來吟唱蜓斧,執(zhí)行的也是殺龍任務,也可以將xml里面的配置改為拯救少女睁冬,可能這個騎士他不喜歡拯救少女吧挎春。
這個例子 初步展示了DI看疙、AOP的思想。