在ssh項目中,是有明確分工的,spring的作用就相當于將struts和hibernate連接起來,是將兩個沒有關系的框架的特性,方法,action都放在spring的配置文件中使他們建立關系。取他門各自所長。而這些做法他們自己不知道,他們是聽命于spring調度的,他的的任務只是做好自己的事情。
這樣做的好處就是任務結構分明,struts只管理顯示與做什么,hibernate只關心怎么做,而spring就相當于領導,所以一切的類都要交給spring的工廠創(chuàng)建,這是一種良好的開發(fā)模式,體現(xiàn)了一種編程思想,最大的好處就是結構分明,便于維護,一旦項目出現(xiàn)問題,只修改spring文件,而不在你復雜的程序中去發(fā)現(xiàn)是誰在調用誰。
簡而言之,ssh框架總體是為了解耦合使用的,struts管理表示層,spring管理業(yè)務邏輯層,hibernate管理持久化層,3個框架互相不關聯(lián),spring調用hibernate、struts調用spring來做方法調用,好處在于spring面向接口的設計,只要你的接口不變,impl變動在配置文件中配置就好了,這樣在工程實施后,可以實現(xiàn)軟編碼,在異地調用用的配置文件直接修改配置文件調用已經寫好的類,來增加功能。
下面結合實例理解解容器,DI,IOC,耦合,解耦等Spring所涉及的概念,同時了解Spring的最基本也是最核心的使用方法。
1.Spring容器
Spring容器負責對象的實例化,對象生命周期的管理,被Spring管理的對象稱之為Bean。
例如有Soldier類需要交由Spring容器管理,我們先編寫類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
package com.hb; public class Soldier { private String name; public String getName() { return name; } public void setName(String name) { this .name = name; } } |
在Spring配置文件中添加如下配置
<</SPAN>bean id="s1" class="com.hb.Soldier"></</SPAN>bean>
初始化Spring容器
1
2
3
4
5
6
7
8
9
10
11
|
public class Test { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext( "applicationContext.xml" ); } } |
從Spring容器中取得對象實例
1
|
Soldier s1 = (Soldier) context.getBean( "s1" ); |
Spring默認使用單例的方式創(chuàng)建對象。可以通過修改的配置改變成其它創(chuàng)建方式。這個屬性為Scope,稱之為作用域或生命周期,它的值為singleton(單例,默認值),prototype(每次產生一個新的實例)等。
1
|
<</SPAN>bean id= "s1" class = "com.hb.Soldier" scope= "prototype" ></</SPAN>bean> |
2. 注入方式有setter注入,構造注入方式,接口注入(不需掌握)。建議多使用Setter注入方式。
Setter注入:
Soldier類中有一個屬性name,如何在創(chuàng)建Soldier的時候使name的值變?yōu)?rdquo;RANBO”?
配置如下:
1
2
3
4
5
|
<</SPAN>bean id= "s1" class = "com.hb.Soldier" > <</SPAN>property name= "name" value= "RANBO" /> </</SPAN>bean> |
這樣創(chuàng)建的Soldier對象的name屬性就有值了,測試代碼:
1
2
3
4
5
6
7
8
9
|
public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext( "applicationContext.xml" ); Soldier s1 = (Soldier) context.getBean( "s1" ); System.out.println(s1.getName()); } |
構造注入:
我們先修改下Soldier類,給它添加一個構造方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
package com.hb; public class Soldier { private String name; public Soldier(String name) { this .name = name; } public String getName() { return name; } } |
配置如下:
1
2
3
4
5
|
<</SPAN>bean id= "s1" class = "com.hb.Soldier" > <</SPAN>constructor-arg value= "RANBO" ></</SPAN>constructor-arg> </</SPAN>bean> |
測試結果同上。
3. 依賴
當A對象使用了B對象的方法,A對B產生依賴,稱之為A依賴B。下面的例子中Soldier類依賴HandGun類。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
package com.hb; public class Soldier { public void fight(){ HandGun handGun = new HandGun(); handGun.killEnemy(); } } package com.hb; public class HandGun { public void killEnemy(){ System.out.println( "手槍殺敵" ); } } |
當HandGun發(fā)生變化時,必然導致Soldier必須做相應修改,同時,當Soldier需要使用OtherGun時也必須重新編寫代碼,導致代碼重用度不高。
當對象之間的依賴關系很強時(耦合),會使程序代碼死板,不利于后期的維護和擴展。降低對象之間的依賴關系稱之為解耦。Spring能夠很好的解決這一問題。
4. 控制反轉(Inversion of Control,簡稱IOC)和依賴注入(Dependence Inject簡稱DI)
我們運用Spring的setter注入方式解決HandGun和Soldier的耦合問題。修改Soldier的代碼,將HandGun定義為Soldier的屬性并提供setter方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
package com.hb; public class Soldier { private HandGun handGun; public void setHandGun(HandGun handGun) { this .handGun = handGun; } public void fight(){ handGun.killEnemy(); } } |
配置如下
1
2
3
4
5
6
7
8
9
10
11
|
<</SPAN>bean id= "s1" class = "com.hb.Soldier" > <</SPAN>property name= "handGun" > <</SPAN>ref bean= "handgun" ></</SPAN>ref> </</SPAN>property> </</SPAN>bean> <</SPAN>bean id= "handgun" class = "com.hb.HandGun" ></</SPAN>bean> |
到這里,我們已經降低了HandGun和Soldier的部分依賴關系,至少在Soldier中不用再自己去實例化HandGun了。然而并沒有徹底解決問題,Soldier中仍然可以看到HandGun類,因此我們使用接口進一步改進代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
package com.hb; public interface Weapon { void killEnemy(); } package com.hb; public class HandGun implements Weapon{ public void killEnemy(){ System.out.println( "手槍殺敵" ); } } package com.hb; public class Soldier { private Weapon weapon; public void setWeapon(Weapon weapon) { this .weapon = weapon; } public void fight(){ weapon.killEnemy(); } } |
配置如下
1
2
3
4
5
6
7
8
9
10
11
|
<</SPAN>bean id= "s1" class = "com.hb.Soldier" > <</SPAN>property name= "weapon" > <</SPAN>ref bean= "handgun" ></</SPAN>ref> </</SPAN>property> </</SPAN>bean> <</SPAN>bean id= "handgun" class = "com.hb.HandGun" ></</SPAN>bean> |
測試:
1
2
3
4
5
6
7
|
ApplicationContext context = new ClassPathXmlApplicationContext( "applicationContext.xml" ); Soldier s1 = (Soldier) context.getBean( "s1" ); s1.fight(); |
至此,我們使用Spring很好的解決了HandGun和Soldier的耦合問題。Soldier類中再也看不到HandGun的蹤影了,Soldier只依賴于接口,而最終Soldier還是使用了HandGun,這是為什么呢?Spring在這里管理了單個的對象,也管理了對象之間即Soldier和HandGun的依賴關系。原本是由Soldier控制HandGun的實例化的,轉變?yōu)橛蒘pring容器來控制,這里發(fā)生了控制權的轉移,這就是控制反轉(Inversion of Control,簡稱IOC)。當Soldier需要HandGun時,Spring會自動將HandGun對象注入給Soldier,這就是依賴注入了。
以上這篇淺談SSH框架中spring的原理就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持服務器之家。