Java 框架學習之 Spring

一. Spring 框架介紹喧笔。

Spring 框架是 一個基于 IoC 和 AOP 的 J2EE 框架书闸。
IoC(控制反轉(zhuǎn),也叫作依賴注入) 是實現(xiàn) Spring 的基礎(chǔ)利凑。IoC的作用是將控制權(quán)交給調(diào)用方梗劫,由調(diào)用方?jīng)Q定到底應(yīng)該創(chuàng)建那個具體的實例截碴。
IoC 在 Spring 框架中的作用是將以前程序員手動自己通過 new 創(chuàng)建對象交由 Spring 容器來進行梳侨。
AOP (面向切面編程) 即將需要實現(xiàn)的功能分為核心功能和周邊功能日丹,在 Spring AOP編程思想中走哺,就將周邊事物確定為切面。
核心功能和周邊功能可以分開開發(fā)哲虾,最后整合編織在一起運行,就是 AOP束凑。

二. Spring框架的依賴

首先需要 Spring 框架的 jar 包晒旅。
這里使用How2j 網(wǎng)站提供的整理好的 jar 包汪诉。點擊下載
另外废恋,推廣一下這個網(wǎng)站,還是挺好用的拟烫。 How2j

三. Spring框架初探

Spring Ioc 部分

要想使用 Spring嘉赎,首先我們需要對其進行配置置媳。
在項目的根目錄創(chuàng)建 applicationContext.xml 文件,并在其中添加一下內(nèi)容赃份。

<!-- applicationContext.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"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
   http://www.springframework.org/schema/beans 
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
   http://www.springframework.org/schema/aop 
   http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
   http://www.springframework.org/schema/tx 
   http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
   http://www.springframework.org/schema/context      
   http://www.springframework.org/schema/context/spring-context-3.0.xsd">
</beans>

創(chuàng)建我們需要的實體類Category,它有兩個屬性分別為 int 類型的 id 與 String 類型的 name奢米,并分別實現(xiàn)他們的 getter 與 setter 方法抓韩。

// Category.java
public class Category {
    private int id;
    private String name;
    //getter,setter方法
}

然后修改我們的 appalicationContext.xml 文件鬓长。在 beans 標簽內(nèi)添加我們對應(yīng)實體類的 bean 標簽谒拴。添加方法如下:

<!-- applicationContext.xml -->

<?xml version="1.0" encoding="UTF-8"?>
<beans //...省略重復部分>

<bean name="category" class="com.tadecather.spring.pojo.Category">
    <property name="name" value="category 1" />
    <property name="id" value="12" />
</bean>

</beans>

其中 bean 標簽內(nèi)的 name 屬性是 Spring 尋找實體類時所使用的名稱,相當于時別名涉波; class 屬性 為對應(yīng)實體類的完整名稱英上,也就是 包名+類名。
bean 標簽內(nèi)的 <property> 標簽內(nèi)的 name 為對應(yīng)的實體類的屬性啤覆,value 標簽為屬性具體值苍日。
可以每一個標簽都配置屬性,也可以選擇一部分甚至全部都不設(shè)置屬性窗声,那么將采用對應(yīng)類型的默認值為其賦值相恃。

接下來編寫我們的測試代碼:

//TestSpring.java

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.tadecather.spring.pojo.Category;
import com.tadecather.spring.pojo.Product;
 
public class TestSpring {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext(
                new String[]{"applicationContext.xml"});
        Category c = (Category)context.getBean("category");
        System.out.println(c.getName() + ":" + c.getId());
        Product p = (Product) context.getBean("product");
        System.out.println(p.getId() + "name: " + p.getName());
    }
}

執(zhí)行結(jié)果如下圖所示:

如果 Product類中有一個 Category 類,那么我們應(yīng)該要如何實現(xiàn)吶笨觅?
在 Product 類中添加屬性Category category拦耐。 Category category; 并實現(xiàn)它的 getter,setter 方法。
修改 appalicationContext.xml 添加 另外一個 bean 標簽见剩。如下:

<!-- 
    <bean name="product" class="com.tadecather.spring.pojo.Product">
        <property name="id" value="13" />
        <property name="name" value="apple" />
        <property name="price" value="12.33" />
        <property name="category" ref="category" />
    </bean>

使用 ref 屬性指向我們已經(jīng)定義好的 category 的標簽上杀糯。
修改TestSpring.java 的最后輸出語句為 System.out.println(p.getCategory().getName());得到如下結(jié)果:

通過在上面的代碼中使用 ref 屬性,我們實現(xiàn)了注入對象的功能苍苞。
接下來固翰,我們通過注解的方式實現(xiàn)對象注入:

  1. 在 applicationContext.xml 中添加這樣一行:<context:annotation-config/>,同時刪除上面 ref 的那一行。
  2. 在Product.java 的 category 屬性前加上 @Autowired 注解。
  3. 然后運行我們的 TestSpring.java 得到如下結(jié)果:

    (是的倦挂,結(jié)果一樣畸颅,原諒我用了一張圖!)
  4. 在 setCategory() 前面添加 @AutoWired 達到同樣的功能方援。
  5. 注解 @Resource(name="category") 也可以達到同樣效果没炒。

最后,我們來實現(xiàn)對 Bean 的注解犯戏。
刪除 appalication 中的<bean> 子標簽送火,以及剛剛添加的 <context:annotation-config/>
然后添加一行 <context:component-scan base-package="com.tadecather.spring.pojo"/>,告知我們的 Bean 組件在 這個包中先匪。
最后种吸,在Category 以及 Product 類的前面添加注釋 @Component

運行我們的測試程序,結(jié)果如下:

Spring AOP 部分

使用標簽實現(xiàn)

首先創(chuàng)建需要用到的核心業(yè)務(wù)類,里面只有一個方法 doSomeService()呀非,用來簡單的輸出一句話坚俗。

// ProductService.java
public class ProductService {
    public void doSomeService(){
        System.out.println("do someService!");
    }
}

接下來,實現(xiàn) Aspect 類岸裙,LoggerAspect 類猖败,里面有一個 log() 方法,接受一個 ProceedingJoinPoint 參數(shù)降允,返回一個 Object 對象恩闻。

// LoggeAspect.java 
import org.aspectj.lang.ProceedingJoinPoint;
public class LoggerAspect {
    public Object log(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("start proceeding!" + joinPoint.getSignature().getName());
        Object object = joinPoint.proceed();
        System.out.println("end proceeding!" + joinPoint.getSignature().getName());
        return object;
    }
}

ProceedingJoinPoint 對象的 proceed() 會拋出一個 ThrowAble 。
最后修改 applicationContext.xml 如下:

<!-- applicationContext.xml 部分
<?xml version="1.0" encoding="UTF-8"?>
...

    <bean name="s" class="com.tadecather.spring.service.ProductService" />
    <bean id="loggerAspect" class="com.tadecather.spring.aspect.LoggerAspect"/>

    <aop:config>
        <aop:pointcut id="loggerCutpoint"
            expression=
            "execution(* com.tadecather.spring.service.ProductService.*(..)) "
        <aop:aspect id="logAspect" ref="loggerAspect">
            <aop:around pointcut-ref="loggerCutpoint" method="log"/>
        </aop:aspect>
    </aop:config>     
</beans>

在 xml 文件中剧董,我們首先添加了 ProductService 與 LoggerAspect 的 Bean 標簽幢尚。
然后,添加 <aop:config> 標簽翅楼,在標簽內(nèi)對 AOP 進行配置尉剩。
需要配置的標簽有兩個,第一個為 <aop:pointcut> 這個標簽指定程序在運行到哪一步時會觸發(fā)下面一個標簽 <aop:aspect> 的內(nèi)容毅臊。
其中边涕,expression 屬性指明觸發(fā)的條件 ,本例子中的觸發(fā)條件為褂微,當執(zhí)行到 ProductService 類中的任何一個方法時功蜓,執(zhí)行下面的切面函數(shù)。 第一個*指的是任意返回值宠蚂,第二個*是任意函數(shù)函數(shù)式撼,括號內(nèi)的 .. 表示任意參數(shù)。

執(zhí)行的步驟大致就是求厕,執(zhí)行到標記的函數(shù)的時候著隆,會將程序的控制權(quán)交給切面函數(shù)扰楼,然后會在切面函數(shù)中執(zhí)行需要執(zhí)行的函數(shù),當然美浦,可以在執(zhí)行之前添加一些別的操作弦赖,例如打印日志。

執(zhí)行程序,效果如下:

使用注釋實現(xiàn)

使用注釋注入對象的方法修改 ProductService 類和 LoggerAspect 類浦辨。
然后在LoggeerAspect 類中加入實現(xiàn) AOP的注釋蹬竖,修改后的 LoggerAspect 如下:

// LoggerAspect.java
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component("loggerAspect")
public class LoggerAspect {
    @Around(value = "execution(* com.tadecather.spring.service.ProductService.*(..))")
    public Object log(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("start proceeding!" + joinPoint.getSignature().getName());
        Object object = joinPoint.proceed();
        System.out.println("end proceeding!" + joinPoint.getSignature().getName());
        return object;
    }
}

@Aspect 直接表明這是一個切面
@Component("loggerAspect") 注解,表明這是一個別名為 loggerAspect 的 Bean 組件
@Around(value = "execution(* com.how2java.service.ProductService.*(..))") 表明在使用
com.tadecather.spring.service 的任意方法時流酬,會觸發(fā)這個切面處理函數(shù)币厕。

并在 applicationContext.xml 文件中加入掃描路徑,與自動處理 AOP 的語句芽腾。

<!-- applicationContext.xml 部分 -->
    <context:component-scan base-package="com.tadecather.spring.service"/>
    <context:component-scan base-package="com.tadecather.spring.aspect"/>
    <aop:aspectj-autoproxy/> 

執(zhí)行 TestSpring.java 效果如下:


注解方式測試

要求:需要使用到測試依賴 jar 文件:junit-4.12.jar 和 hamcrest-all-1.3.jar 旦装,下載并導入項目。
junit-4.12.jar
hamcrest-all-1.3.jar
操作:

  1. @RunWith(SpringJUnit4ClassRunner.class) 標注這是一個測試類
  2. @ContextConfiguration("classpath:applicationContext.xml") 配置文件位置
  3. @Test 測試方法
  4. 將 TestSpring 修改為下面形式
@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration("classpath:applicationContext.xml")
public class TestSpring {
    @Autowired
    Category c;
    @Test
    public void test(){
        System.out.println(c.getName());
    }
}
  1. 測試結(jié)果如下:

到此摊滔,Spring 框架的初步學習阴绢,到此結(jié)束。
以上內(nèi)容 來自這里艰躺!
然后加上了一點我的學習思考呻袭。

2017.09.23 tadecather

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市描滔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌踪古,老刑警劉巖含长,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異伏穆,居然都是意外死亡拘泞,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門枕扫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來陪腌,“玉大人,你說我怎么就攤上這事烟瞧∈迹” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵参滴,是天一觀的道長强岸。 經(jīng)常有香客問我,道長砾赔,這世上最難降的妖魔是什么蝌箍? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任青灼,我火速辦了婚禮,結(jié)果婚禮上妓盲,老公的妹妹穿的比我還像新娘杂拨。我一直安慰自己,他們只是感情好悯衬,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布弹沽。 她就那樣靜靜地躺著,像睡著了一般甚亭。 火紅的嫁衣襯著肌膚如雪贷币。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天亏狰,我揣著相機與錄音役纹,去河邊找鬼。 笑死暇唾,一個胖子當著我的面吹牛促脉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播策州,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼瘸味,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了够挂?” 一聲冷哼從身側(cè)響起旁仿,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎孽糖,沒想到半個月后枯冈,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡办悟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年尘奏,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片病蛉。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡炫加,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出铺然,到底是詐尸還是另有隱情俗孝,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布魄健,位于F島的核電站驹针,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏诀艰。R本人自食惡果不足惜柬甥,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一饮六、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧苛蒲,春花似錦卤橄、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至漏健,卻和暖如春嚎货,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蔫浆。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工殖属, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人瓦盛。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓洗显,卻偏偏與公主長得像,于是被迫代替她去往敵國和親原环。 傳聞我的和親對象是個殘疾皇子挠唆,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容