# 開(kāi)始spring之旅
## 歷史
javabean -> EJB -> spring
## why
spring 簡(jiǎn)化了企業(yè)級(jí)系統(tǒng)開(kāi)發(fā). 原因是EJB太復(fù)雜了
1.好的設(shè)計(jì)比實(shí)現(xiàn)技術(shù)更重要
2.通過(guò)接口耦合的javabean是一個(gè)很好的模型
3.代碼應(yīng)該容易被測(cè)試
spring是一個(gè)輕量級(jí)的IOC和AOP框架亮蛔。
## spring模塊
1.core
2.AOP
3.O/R 映射
4.web context
5.applicaiton context
6.jdbc & dao
7.mvc
## spring hello world
首選寫(xiě)接口類(lèi)
public interface GreetingService {
public void sayHello();
}
第二步實(shí)現(xiàn)類(lèi)
public class GreetingServiceImpl implements GreetingService {
private String greeting;
public String getGreeting() {
return greeting;
}
public void setGreeting(String greeting) {
this.greeting = greeting;
}
public void sayHello() {
System.out.println(this.greeting);
}
}
第三步 配置bean.xml
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-3.0.xsd">
hello world
第四步 使用
public class main {
public static??void main(String [] args) {
ClassPathResource resource = new ClassPathResource("beans/beans.xml");
System.out.println(resource.getPath());
BeanFactory factory = new GenericXmlApplicationContext(resource);
GreetingService greeting = (GreetingService) factory.getBean("greetService");
greeting.sayHello();
}
}
但是這樣使用和
GreetingService greeting = new GreetingServiceImpl()
相比為一個(gè)的區(qū)別就是把GreetingService的實(shí)例化用配置來(lái)代替了. 這就是傳說(shuō)中的IOC
##理解IOC
IOC ,即反轉(zhuǎn)控制眷细。 是spring的核心爷辱。
當(dāng)然用 依賴(lài)注入來(lái)解釋會(huì)更容易理解。 當(dāng)A使用了B, 在A實(shí)例化的時(shí)候路狮,也必須實(shí)例化B,表明類(lèi)A對(duì)B有了依賴(lài)愤钾。 我們把B的實(shí)例化抽取出來(lái)蛙讥,而是采用在外部系統(tǒng)控制B的實(shí)例化并負(fù)責(zé)注入到A中,這樣就實(shí)現(xiàn)了A和B的耦合遇西。這就是所謂的依賴(lài)注入馅精。
## IOC例子
騎士找圣杯
public class KnightOfRoundTable {
private String name;
private HolyGrailQuest quest;
public KnightOfRoundTable(String name) {
this.name = name;
this.quest = new HolyGrailQuest();
}
public??HolyGrail embarkOnQuest(){
return quest.embark();
}
}
當(dāng)我們寫(xiě)單元測(cè)試的時(shí)候會(huì)發(fā)現(xiàn)當(dāng)寫(xiě)了KnightOfRoundTable的時(shí)候順帶把HolyGrailQuest 也寫(xiě)進(jìn)去了。 因?yàn)镵nightOfRoundTable 和 HolyGrailQuest 耦合在一起了粱檀。
耦合的代碼
-難以測(cè)試洲敢, 難以使用,帶來(lái)典型的"摧毀大堤"的bug
-但是沒(méi)有耦合的代碼什么也做不了
所以我們要管理耦合
其最常見(jiàn)的一個(gè)方法就是面向接口編程
public interface IQuest {
public??HolyGrail embark();
}
同樣:
public interface IKnight {
HolyGrail embarkOnQuest();
}
在 KnightOfRoundTable 中茄蚯,就需要把任務(wù)裝配進(jìn)去
public void setQuest(IQuest quest) {
this.quest = quest;
}
然后配置bean:
undefinedundefined
John
創(chuàng)建系統(tǒng)組件之間關(guān)聯(lián)的動(dòng)作叫做裝配压彭。spring中有很多裝配的方式,其中XML是最常見(jiàn)的一種渗常。
以上是以來(lái)控制的全部: 協(xié)調(diào)依賴(lài)對(duì)象之間合作的責(zé)任壮不,從對(duì)象之間釋放出來(lái)。
## 應(yīng)用AOP
理想的系統(tǒng)是有很多組件組成凳谦,每一個(gè)組件負(fù)責(zé)其中一部分的功能忆畅。但是實(shí)際情況是像日志管理這樣的組件,進(jìn)程侵入到其他系統(tǒng)中。
回答上面的例子家凯, 我們假設(shè)需求變更了缓醋, 每一次騎士做任務(wù)之前,都需要配置一個(gè)吟游詩(shī)人來(lái)歌頌他的事跡
public??HolyGrail embarkOnQuest(){
this.mistrel.compose(this.name, "embark");
return quest.embark();
}
那么問(wèn)題來(lái)了绊诲, 其實(shí)必須每一次都主動(dòng)觸發(fā) mistrel 去干什么送粱。但是騎士騎士不用關(guān)心 mistrel 干了什么事情的。簡(jiǎn)單的說(shuō) mistrel 提供的服務(wù)超出了騎士本來(lái)的責(zé)任掂之,也就是說(shuō)mistrel和騎士的服務(wù)交叉在一起了抗俄。所以把mistrel實(shí)現(xiàn)成切面,并把他的服務(wù)提供給騎士是合理的世舰。
public class Minstrel implements MethodBeforeAdvice {
public void before(Method method, Object[] args, Object target) throws Throwable {
IKnight knight = (IKnight)target;
String name = knight.getName();
System.out.println(name + ":" + knight.embarkOnQuest().toString());
}
}
配置bean
chaper01.knight.IKnight
minstrel
最典型的應(yīng)用就是數(shù)據(jù)庫(kù)的事物动雹。