Spring 基礎學習

1、Spring框架概述

Spring是一個開源免費的框架,爲了解決企業應用開發的複雜性而建立。Spring框架是一個輕量級的解決方案,能夠一站式地構建企業級應用。Spring是模塊化的,因此能夠只使用其中須要的部分。能夠在任何web框架上使用控制反轉(IoC),也能夠只使用Hibernate集成代碼或JDBC抽象層。它支持聲明式事務管理、經過RMI或web服務實現遠程訪問,並可使用多種方式持久化數據。它提供了功能全面的MVC框架,能夠透明地集成AOP到軟件中。java

Spring被設計爲非侵入式的,這意味着你的域邏輯代碼一般不會依賴於框架自己。在集成層(好比數據訪問層),會存在一些依賴同時依賴於數據訪問技術和Spring,可是這些依賴能夠很容易地從代碼庫中分離出來。web

Spring框架是基於Java平臺的,它爲開發Java應用提供了全方位的基礎設施支持,而且它很好地處理了這些基礎設施,因此你只須要關注你的應用自己便可。spring

Spring可使用POJO(普通的Java對象,plain old java objects)建立應用,而且能夠將企業服務非侵入式地應用到POJO。這項功能適用於Java SE編程模型以及所有或部分的Java EE。數據庫

一句話總結:Spring是一個輕量級的控制反轉(IoC)和麪向切面(AOP)的容器(框架)。編程

spring歷史背景:

Rod Johnson在2002年編著的《Expert one on one J2EE design and development》一書中,對Java EE 系統框架臃腫、低效、脫離現實的種種現狀提出了質疑,並積極尋求探索革新之道。以此書爲指導思想,他編寫了interface21框架,這是一個力圖衝破J2EE傳統開發的困境,從實際需求出發,着眼於輕便、靈巧,易於開發、測試和部署的輕量級開發框架。Spring框架即以interface21框架爲基礎,通過從新設計,並不斷豐富其內涵,於2004年3月24日,發佈了1.0正式版。同年他又推出了一部堪稱經典的力做《Expert one-on-one J2EE Development without EJB》,該書在Java世界掀起了軒然大波,不斷改變着Java開發者程序設計和開發的思考方式。在該書中,做者根據本身多年豐富的實踐經驗,對EJB的各類笨重臃腫的結構進行了逐一的分析和否認,並分別以簡潔實用的方式替換之。至此一戰功成,Rod Johnson成爲一個改變Java世界的大師級人物。
傳統J2EE應用的開發效率低,應用服務器廠商對各類技術的支持並無真正統一,致使J2EE的應用沒有真正實現Write Once及Run Anywhere的承諾。Spring做爲開源的中間件,獨立於各類應用服務器,甚至無須應用服務器的支持,也能提供應用服務器的功能,如聲明式事務、事務處理等。
Spring致力於J2EE應用的各層的解決方案,而不是僅僅專一於某一層的方案。能夠說Spring是企業應用開發的「一站式」選擇,並貫穿表現層、業務層及持久層。然而,Spring並不想取代那些已有的框架,而是與它們無縫地整合。

框架特徵:

  • 輕量——從大小與開銷兩方面而言Spring都是輕量的。完整的Spring框架能夠在一個大小隻有1MB多的JAR文件裏發佈。而且Spring所需的處理開銷也是微不足道的。此外,Spring是非侵入式的:典型地,Spring應用中的對象不依賴於Spring的特定類。
  • 控制反轉——Spring經過一種稱做控制反轉(IoC)的技術促進了低耦合。當應用了IoC,一個對象依賴的其它對象會經過被動的方式傳遞進來,而不是這個對象本身建立或者查找依賴對象。你能夠認爲IoC與JNDI相反——不是對象從容器中查找依賴,而是容器在對象初始化時不等對象請求就主動將依賴傳遞給它。
  • 面向切面——Spring提供了面向切面編程的豐富支持,容許經過分離應用的業務邏輯與系統級服務(例如審計(auditing)和事務(transaction)管理)進行內聚性的開發。應用對象只實現它們應該作的——完成業務邏輯——僅此而已。它們並不負責(甚至是意識)其它的系統級關注點,例如日誌或事務支持。
  • 容器——Spring包含並管理應用對象的配置和生命週期,在這個意義上它是一種容器,你能夠配置你的每一個bean如何被建立——基於一個可配置原型(prototype),你的bean能夠建立一個單獨的實例或者每次須要時都生成一個新的實例——以及它們是如何相互關聯的。然而,Spring不該該被混同於傳統的重量級的EJB容器,它們常常是龐大與笨重的,難以使用。
  • 框架——Spring能夠將簡單的組件配置、組合成爲複雜的應用。在Spring中,應用對象被聲明式地組合,典型地是在一個XML文件裏。Spring也提供了不少基礎功能(事務管理、持久化框架集成等等),將應用邏輯的開發留給了你。
  • MVC——Spring的做用是整合,但不只僅限於整合,Spring 框架能夠被看作是一個企業解決方案級別的框架。客戶端發送請求,服務器控制器(由DispatcherServlet實現的)完成請求的轉發,控制器調用一個用於映射的類HandlerMapping,該類用於將請求映射到對應的處理器來處理請求。HandlerMapping 將請求映射到對應的處理器Controller(至關於Action)在Spring 當中若是寫一些處理器組件,通常實現Controller 接口,在Controller 中就能夠調用一些Service 或DAO 來進行數據操做 ModelAndView 用於存放從DAO 中取出的數據,還能夠存放響應視圖的一些數據。 若是想將處理結果返回給用戶,那麼在Spring 框架中還提供一個視圖組件ViewResolver,該組件根據Controller 返回的標示,找到對應的視圖,將響應response 返回給用戶。
  • 全部Spring的這些特徵使你可以編寫更乾淨、更可管理、而且更易於測試的代碼。它們也爲Spring中的各類模塊提供了基礎支持。

Spring特色:

1.方便解耦,簡化開發設計模式

經過Spring提供的IoC容器,咱們能夠將對象之間的依賴關係交由Spring進行控制,避免硬編碼所形成的過分程序耦合。有了Spring,用戶沒必要再爲單實例模式類、屬性文件解析等這些很底層的需求編寫代碼,能夠更專一於上層的應用。

2.AOP編程的支持安全

經過Spring提供的AOP功能,方便進行面向切面的編程,許多不容易用傳統OOP實現的功能能夠經過AOP輕鬆應付。

3.聲明式事務的支持服務器

在Spring中,咱們能夠從單調煩悶的事務管理代碼中解脫出來,經過聲明式方式靈活地進行事務的管理,提升開發效率和質量。

4.方便程序的測試架構

能夠用非容器依賴的編程方式進行幾乎全部的測試工做,在Spring裏,測試再也不是昂貴的操做,而是隨手可作的事情。例如:Spring對Junit4支持,能夠經過註解方便的測試Spring程序。

5.方便集成各類優秀框架app

Spring不排斥各類優秀的開源框架,相反,Spring能夠下降各類框架的使用難度,Spring提供了對各類優秀框架(如Struts,Hibernate、Hessian、Quartz)等的直接支持。

6.下降Java EE API的使用難度

Spring對不少難用的Java EE API(如JDBC,JavaMail,遠程調用等)提供了一個薄薄的封裝層,經過Spring的簡易封裝,這些Java EE API的使用難度大爲下降。

7.Java 源碼是經典學習範例

Spring的源碼設計精妙、結構清晰、匠心獨運,到處體現着大師對Java設計模式靈活運用以及對Java技術的高深造詣。Spring框架源碼無疑是Java技術的最佳實踐範例。若是想在短期內迅速提升本身的Java技術水平和應用開發水平,學習和研究Spring源碼將會使你收到意想不到的效果。

使用Spring的好處:

1.低侵入式設計,代碼污染極低
2.獨立於各類應用服務器,基於Spring框架的應用,能夠真正實現Write Once,Run Anywhere的承諾
3.Spring的DI機制下降了業務對象替換的複雜性,提升了組件之間的解耦
4.Spring的AOP支持容許將一些通用任務如安全、事務、日誌等進行集中式管理,從而提供了更好的複用
5.Spring的ORM和DAO提供了與第三方持久層框架的良好整合,並簡化了底層的數據庫訪問
6.Spring並不強制應用徹底依賴於Spring,開發者可自由選用Spring框架的部分或所有

Spring組成

Spring 框架是一個分層架構,由 7 個定義良好的模塊組成。Spring 模塊構建在覈心容器之上,核心容器定義了建立、配置和管理 bean 的方式

組成 Spring 框架的每一個模塊(或組件)均可以單獨存在,或者與其餘一個或多個模塊聯合實現。每一個模塊的功能以下:

  • 核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要組件是 BeanFactory,它是工廠模式的實現。BeanFactory 使用控制反轉(IOC) 模式將應用程序的配置和依賴性規範與實際的應用程序代碼分開。
  • Spring 上下文:Spring 上下文是一個配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企業服務,例如 JNDI、EJB、電子郵件、國際化、校驗和調度功能。
  • Spring AOP:經過配置管理特性,Spring AOP 模塊直接將面向方面的編程功能集成到了 Spring 框架中。因此,能夠很容易地使 Spring 框架管理的任何對象支持 AOP。Spring AOP 模塊爲基於 Spring 的應用程序中的對象提供了事務管理服務。經過使用 Spring AOP,不用依賴 EJB 組件,就能夠將聲明性事務管理集成到應用程序中。
  • Spring DAO:JDBC DAO 抽象層提供了有意義的異常層次結構,可用該結構來管理異常處理和不一樣數據庫供應商拋出的錯誤消息。異常層次結構簡化了錯誤處理,而且極大地下降了須要編寫的異常代碼數量(例如打開和關閉鏈接)。Spring DAO 的面向 JDBC 的異常聽從通用的 DAO 異常層次結構。
  • Spring ORM:Spring 框架插入了若干個 ORM 框架,從而提供了 ORM 的對象關係工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。全部這些都聽從 Spring 的通用事務和 DAO 異常層次結構。
  • Spring Web 模塊:Web 上下文模塊創建在應用程序上下文模塊之上,爲基於 Web 的應用程序提供了上下文。因此,Spring 框架支持與 Jakarta Struts 的集成。Web 模塊還簡化了處理多部分請求以及將請求參數綁定到域對象的工做。
  • Spring MVC 框架:MVC 框架是一個全功能的構建 Web 應用程序的 MVC 實現。經過策略接口,MVC 框架變成爲高度可配置的,MVC 容納了大量視圖技術,其中包括 JSP、Velocity、Tiles、iText 和 POI。

Spring 框架的功能能夠用在任何 J2EE 服務器中,大多數功能也適用於不受管理的環境。Spring 的核心要點是:支持不綁定到特定 J2EE 服務的可重用業務和數據訪問對象。毫無疑問,這樣的對象能夠在不一樣 J2EE 環境 (Web 或 EJB)、獨立應用程序、測試環境之間重用。

Spring是一個開源的框架,如今的Spring框架構成了一個體系平臺,經過Spring的官方網站http://www.springsource.org能夠了解到,圍繞着Spring框架自己,還有許多其餘優秀的項目:

SpringFramework(Core):核心項目

Spring Web Flow:工做流項目

Spring Security:安全項目

Spring Batch:批量數據處理項目

Spring Android:Android系統支持項目

Spring Social:社交項目

2、應用實例

接口:

最核心的 jar 包:

  • spring-core
  • spring-bean
  • spring-context

最核心的接口是 BeanFactory,它用來描述 IOC 容器

它很乾淨,很純粹,最主要的方法是 getBean 用來給調用方返回一個實例化好的對象。

在實際運用中,須要一些周邊功能,好比加載資源/國際化/等等,Spring 爲此提供了 ApplicatinContext 接口。它自己是 BeanFactory 的一個實現:

 

能夠看到,ApplicationContext 除了實現了 BeanFactory,還實現了其餘一些實用的接口。所以,它是在 Spring 中操做一切的核心。

這是門面模式的一種典型使用。

配置:

一、傳統的方式 xml

這種方式,充分利用了 xml 文件的優點:

  • 接受度比較高,語法簡單
  • 表達能力比較強
  • 生態比較完整,基於 xml 的校驗、解析等比較完善

因此,最開始的時候,描述工廠裏 bean 聲明的方式,選用的就是 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:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

    <bean id="bs" class="com.learning.spring.BookServiceImpl"></bean>

</beans>

可是:

  • 不少人不喜歡 xml 這種標籤式的語法。寫起來麻煩,看起來不舒服
  • xml 方式過於重型
  • xml 語法校驗雖然強大,但不夠強大
  • xml 雖然靈活,但不夠靈活

因此,就產生了不少其餘的叛逆的想法

2 、基於 Java 的方式進行配置

package com.learning.spring.configuration;

import com.learning.spring.BookDAO;
import com.learning.spring.BookService;
import com.learning.spring.BookServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SuibianSpringConfig {

    @Bean
    public BookService bs(){
        System.out.println(bookDAO());
        if(Math.random() > 0.5){
            return new BookServiceImpl();
        }else{
            return new BookServiceImpl2();
        }
    }

    @Bean
    public BookDAO bookDAO(){
        return new BookDAO();
    }
}

3 、混合雙打(XML+Java)

Java Style 中混入 XML Style:

package com.learning.spring.configuration;

import com.learning.spring.BookDAO;
import com.learning.spring.BookService;
import com.learning.spring.BookServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;

@Configuration
@ImportResource(locations = "learning/spring/my-spring.xml")
public class SuibianSpringConfig2 {

    @Bean
    public BookService bs1() {
        System.out.println(bookDAO());
        if(Math.random() > 0.5){
            return new BookServiceImpl();
        }else{
            return new BookServiceImpl2();
        }
    }

    @Bean
    public BookDAO bookDAO () {
        return new BookDAO();
    }

}

XML style 中混入 Java Style:

<?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:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

    <bean id="bs" class="com.learning.spring.BookServiceImpl"></bean>

    <bean class="com.learning.spring.configuration.SuibianSpringConfig2" />

</beans>

四、裝配 (Wiring)

建立應用對象之間協做關係的行爲,一般稱爲裝配 (Wiring)。這是依賴注入 (DI) 的本質。

裝配的基礎,是使用配置文件對 Bean 的關係進行聲明。

總結起來,在 Spring 中,聲明 Bean 一共有三種方式:

  1. 在 XML Style 的配置中,使用 <bean /> 節點
  2. 在 Java Style 的配置中,使用 @Bean 註解
  3. 開啓 Component 掃描,而後使用相關注解: @Component/@Controller/@Service/@Repository

4.1 Wiring in 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:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

    <!--有參構建-->
    <bean class="com.learning.components.Goal" id="goal">
        <property name="name" value="多利"/>
        <property name="countOfLegs" value="4"/>
        <property name="aliases">
            <ref bean="xx1"/>
        </property>
    </bean>

    <!--集合-->
    <util:list id="xx1">
        <value>value1</value>
        <value>value2</value>
        <value>value3</value>
    </util:list>

    <!--設置別名-->
    <alias name="bookDAO" alias="bookDao"/>
    <alias name="bookDAO" alias="bookdao"/>

    <!--引入外部xml文件-->
    <import resource="dierge.xml"/>

</beans>

另外:

  • denpend-on 定義順序
  • parent 定義繼承
  • scope 定義初始化策略
  • lazy 延遲初始化
  • alias 定義別名
  • import 引入其餘的定義文件

實例:

Goal類代碼以下:

package com.learning.components;


import java.util.List;

public class Goal {
    private String name;
    private int countOfLegs;

    private List<String> aliases;

    public List<String> getAliases() {
        return aliases;
    }

    @Override
    public String toString() {
        return "Goal{" +
                "name='" + name + '\'' +
                ", countOfLegs=" + countOfLegs +
                ", aliases=" + aliases +
                '}';
    }

    public void setAliases(List<String> aliases) {
        this.aliases = aliases;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getCountOfLegs() {
        return countOfLegs;
    }

    public void setCountOfLegs(int countOfLegs) {
        this.countOfLegs = countOfLegs;
    }
}

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:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

    <bean id="bs" class="com.learning.spring.BookServiceImpl"></bean>

    <bean class="com.learning.spring.configuration.SuibianSpringConfig2" />

    <!--有參構建-->
    <bean class="com.learning.components.Goal" id="goal">
        <property name="name" value="多利"/>
        <property name="countOfLegs" value="4"/>
        <property name="aliases">
            <ref bean="xx1"/>
        </property>
    </bean>

    <!--集合-->
    <util:list id="xx1">
        <value>value1</value>
        <value>value2</value>
        <value>value3</value>
    </util:list>

    <!--設置別名-->
    <alias name="bookDAO" alias="bookDao"/>
    <alias name="bookDAO" alias="bookdao"/>

    <!--引入外部xml文件-->
    <import resource="dierge.xml"/>

</beans>

Main類代碼以下:

package com.learning.components;

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

public class Main {

    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("learning/spring/my-spring.xml");
        Goal goal = (Goal) applicationContext.getBean("goal");
        System.out.println(goal);
    }

}

運行結果:

相關文章
相關標籤/搜索