Spring核心技術詳解(一)

1、Sring簡介

Spring是一個分層的Java SE/EE應用一站式的輕量級開源框架。Spring核心是IOCAOP
Spring主要優勢包括:java

  • 方便解耦,簡化開發,經過Spring提供的IoC容器,咱們能夠將對象之間的依賴關係交由Spring進行控制,避免硬編碼形成的程序耦合度高。
  • AOP編程的支持,經過Spring提供的AOP功能,方便進行面向切面編程。
  • 聲明式事務的支持,在Spring中,咱們能夠從單調煩悶的事務管理代碼中解脫出來,經過聲明式方式靈活地進行事務的管理,提升開發效率和質量。
  • 方便程序的測試,能夠用非容器依賴的編程方式進行幾乎全部的測試工做。
  • 方便集成各類優秀框架,Spring提供了對各類優秀框架的直接支持。

2、Spring體系結構

以下圖所示,整個spring框架按其所屬功能能夠劃分爲五個主要模塊,這五個模塊幾乎爲企業應用提供了所需的一切,從持久層、業務層到表現層都擁有相應的支持,這就是爲何稱Spring是一站式框架的緣由。
web


核心模塊(Core Container)

  Spring的核心模塊實現了IoC的功能,它將類和類之間的依賴從代碼中脫離出來,用配置的方式進行依賴關係描述。由IoC容器負責類的建立,管理,獲取等。BeanFactory接口是Spring框架的核心接口,實現了容器不少核心的功能。spring

  Context模塊構建於核心模塊之上,擴展了BeanFactory的功能,包括國際化,資源加載,郵件服務,任務調度等多項功能。ApplicationContext是Context模塊的核心接口。express

  表達式語言(Expression Language)是統一表達式語言(EL)的一個擴展,支持設置和獲取對象屬性,調用對象方法,操做數組、集合等。使用它能夠很方便的經過表達式和Spring IoC容器進行交互。編程

AOP模塊

Spring AOP模塊提供了知足AOP Alliance規範的實現,還整合了AspectJ這種AOP語言級的框架。經過AOP能下降耦合。數組

數據訪問集成模塊(Data Access/Integration )

該模塊包括了JDBC、ORM、OXM、JMS和事務管理:緩存

  • 事務模塊:該模塊用於Spring管理事務,只要是Spring管理對象都能獲得Spring管理事務的好處,無需在代碼中進行事務控制了,並且支持編程和聲明性的事務管理。
  • JDBC模塊:提供了一個JBDC的樣例模板,使用這些模板能消除傳統冗長的JDBC編碼還有必須的事務控制,並且能享受到Spring管理事務的好處。
  • ORM模塊:提供與流行的「對象-關係」映射框架的無縫集成,包括hibernate、JPA、MyBatis等。並且可使用Spring事務管理,無需額外控制事務。
  • OXM模塊:提供了一個對Object/XML映射實現,將Java對象映射成XML數據,或者將XML數據映射成java對象,Object/XML映射實現包括JAXB、Castor、XMLBeans和XStream。
  • JMS模塊:用於JMS(Java Messaging Service),提供一套「消息生產者、消息消費者」模板用於更加簡單的使用JMS,JMS用於在兩個應用程序之間,或分佈式系統中發送消息,進行異步通訊。

Web模塊

該模塊創建在ApplicationContext模塊之上,提供了Web應用的功能,如文件上傳、FreeMarker等。Spring能夠整合Struts2等MVC框架。此外,Spring本身提供了MVC框架Spring MVC。bash

測試模塊

Spring能夠用非容器依賴的編程方式進行幾乎全部的測試工做,支持JUnit和TestNG等測試框架。服務器


3、初識Ioc與DI

咱們首先來說解一下IoC的概念。IoC(控制反轉:Inverse of Control)是Spring容器的核心,可是IoC這個概念卻比較晦澀,讓人不太容易望文生義。app

一、IoC控制反轉和DI依賴注入

  傳統程序設計中,咱們須要使用某個對象的方法,須要先經過new建立一個該對象,咱們這時是主動行爲;而IoC是咱們將建立對象的控制權交給IoC容器,這時是由容器幫忙建立及注入依賴對象,咱們的程序被動的接受IoC容器建立的對象,控制權反轉,因此叫控制反轉。

  因爲IoC確實不夠開門見山,因此提出了DI(依賴注入:Dependency Injection)的概念,即讓第三方來實現注入,以移除咱們類與須要使用的類之間的依賴關係。總的來講,IoC是目的,DI是手段,建立對象的過程每每意味着依賴的注入。咱們爲了實現IoC,讓生成對象的方式由傳統方式(new)反轉過來,須要建立相關對象時由IoC容器幫咱們注入(DI)。

  簡單的說,就是咱們類裏須要另外一個類,只須要讓Spring幫咱們建立 ,這叫作控制反轉;而後Spring幫咱們將須要的對象設置到咱們的類中,這叫作依賴注入

二、常見的幾種注入方法

  • 使用有參構造方法注入
public class  User{
    private String name;
    public User(String name){
        this.name=name;
    }
} 

    User user=new User("tom");複製代碼
  • 使用屬性注入
public class  User{
    private String name;
    public void setName(String name){
        this.name=name;
    }
}

     User user=new User();
     user.setName("jack");複製代碼
  • 使用接口注入
// 將調用類全部依賴注入的方法抽取到接口中,調用類經過實現該接口提供相應的注入方法。 

public interface Dao{
    public void delete(String name);
} 

public class DapIml implements Dao{
    private String name;
    public void delete(String name){
        this.name=name;
    }
}複製代碼

經過容器完成依賴關係的注入

上面的注入方式都須要咱們手動的進行注入,若是有一個第三方容器能幫助咱們完成類的實例化,以及依賴關係的裝配,那麼咱們只須要專一於業務邏輯的開發便可。Spring就是這樣的容器,它經過配置文件或註解描述類和類之間的依賴關係,自動完成類的初始化和依賴注入的工做。

三、Spring的IoC例子

(1) 建立工程,導入jar包

這裏咱們只是作IoC的操做,因此只須要導入核心模塊裏的jar包,beans、core、context、expression等。由於spring中並無日誌相關的jar包,因此咱們還須要導入log4j和commons-logging。

(2) 建立一個類

public class User {
    public void add(){
        System.out.println("add.....");
    }
}複製代碼

(3) 建立一個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="user" class="com.cad.domain.User"/>        
</beans>複製代碼

(4) 進行測試

//這只是用來測試的代碼,後期不會這麼寫
public class Test {

    @org.junit.Test
    public void test(){
        //加載配置文件
        ApplicationContext context=new ClassPathXmlApplicationContext("bean.xml");
        //獲取對象
        User user=(User) context.getBean("user");
        System.out.println(user);
        //調用方法
        user.add();
    }
}複製代碼

在容器啓動時,Spring會根據配置文件的描述信息,自動實例化Bean並完成依賴關係的裝配,從容器中便可得到Bean實例,就能夠直接使用。Spring爲何僅憑一個簡單的配置文件,就能神奇的實例化並配置好程序使用的Bean呢?答案是經過 Java的反射技術

四、Spring的DI例子

咱們的service層老是用到dao層,之前咱們老是在Service層new出dao對象,如今咱們使用依賴注入的方式向Service層注入dao層。

// UserDao
public class UserDao {
    public void add(){
        System.out.println("dao.....");
    }
}

// UserService
public class UserService {
    UserDao userdao;
    public void setUserdao(UserDao userdao){
        this.userdao=userdao;
    }

    public void add(){
        System.out.println("service.......");
        userdao.add();
    }
}

-------------------------------分割線--------------------------

// 配置文件
<bean id="userdao" class="com.cad.domain.UserDao"></bean> 
//這樣在實例化service的時候,同時裝配了dao對象,實現了依賴注入
<bean id="userservice" class="com.cad.domain.UserService">
    //ref爲dao的id值
    <property name="userdao" ref="userdao"></property>
</bean>複製代碼


4、Spring資源訪問神器——Resource接口

JDK提供的訪問資源的類(如java.NET.URL,File)等並不能很好很方便的知足各類底層資源的訪問需求。Spring設計了一個Resource接口,爲應用提供了更強的訪問底層資源的能力,該接口擁有對應不一樣資源類型的實現類。

一、Resource接口的主要方法

  • boolean exists():資源是否存在
  • boolean isOpen():資源是否打開
  • URL getURL():返回對應資源的URL
  • File getFile():返回對應的文件對象
  • InputStream getInputStream():返回對應資源的輸入流

Resource在Spring框架中起着不可或缺的做用,Spring框架使用Resource裝載各類資源,包括配置文件資源,國際化屬性資源等。

二、Resource接口的具體實現類

  • ByteArrayResource:二進制數組表示的資源
  • ClassPathResource:類路徑下的資源 ,資源以相對於類路徑的方式表示
  • FileSystemResource:文件系統資源,資源以文件系統路徑方式表示,如d:/a/b.txt
  • InputStreamResource:對應一個InputStream的資源
  • ServletContextResource:爲訪問容器上下文中的資源而設計的類。負責以相對於web應用根目錄的路徑加載資源
  • UrlResource:封裝了java.net.URL。用戶可以訪問任何能夠經過URL表示的資源,如Http資源,Ftp資源等

三、Spring的資源加載機制

爲了訪問不一樣類型的資源,必須使用相應的Resource實現類,這是比較麻煩的。Spring提供了一個強大的加載資源的機制,僅經過資源地址的特殊標識就能夠加載相應的資源。首先,咱們瞭解一下Spring支持哪些資源類型的地址前綴:

  • classpath:例如classpath:com/cad/domain/bean.xml。從類路徑中加載資源
  • file:例如 file:com/cad/domain/bean.xml.使用UrlResource從文件系統目錄中加載資源。
  • http:// 例如www.baidu.com/resource/be… 使用UrlResource從web服務器加載資源
  • ftp:// 例如frp://10.22.10.11/bean.xml 使用UrlResource從ftp服務器加載資源

Spring定義了一套資源加載的接口。ResourceLoader接口僅有一個getResource(String location)的方法,能夠根據資源地址加載文件資源。資源地址僅支持帶資源類型前綴的地址,不支持Ant風格的資源路徑表達式。ResourcePatternResolver擴展ResourceLoader接口,定義新的接口方法getResources(String locationPattern),該方法支持帶資源類型前綴以及Ant風格的資源路徑的表達式。PathMatchingResourcePatternResolver是Spring提供的標準實現類。

四、例子

public class Test {
    public static void main(String[] args) throws IOException {
        ResourceLoader resloLoader = new DefaultResourceLoader();
        Resource res = resloLoader.getResource("https://www.baidu.com/");
        System.out.println(res instanceof UrlResource); // true
        BufferedReader bf = new BufferedReader(new InputStreamReader(res.getInputStream()));
        StringBuilder sb = new StringBuilder();
        String temp = null;
        while ((temp = bf.readLine())!= null) {
            sb.append(temp);
        }
        System.out.println(sb.toString());

        System.out.println("\n-----------------------------\n");
        res = resloLoader.getResource("classpath:test.txt");
        bf = new BufferedReader(new InputStreamReader(res.getInputStream()));
        sb = new StringBuilder();
        temp = null;
        while ((temp = bf.readLine())!= null) {
            sb.append(temp);
        }
        System.out.println(sb.toString());

        System.out.println("\n-----------------------------\n");
        res = resloLoader.getResource("file:C:\\Users\\ricco\\Desktop\\test\\test.txt");
        bf = new BufferedReader(new InputStreamReader(res.getInputStream()));
        sb = new StringBuilder();
        temp = null;
        while ((temp = bf.readLine())!= null) {
            sb.append(temp);
        }
        System.out.println(sb.toString());
    }
}複製代碼

5、Spring的Ioc容器詳解

一、BeanFactory

  BeanFactory是一個類工廠,和傳統的類工廠不一樣,傳統的類工廠僅負責構造一個類或幾個類的實例;而BeanFactory能夠建立並管理各類類的對象,Spring稱這些被建立和管理的Java對象爲Bean。

  BeanFactory是一個接口,Spring爲BeanFactory提供了多種實現,最經常使用的就是XmlBeanFactory。其中,BeanFactory接口最主要的方法就是getBean(String beanName),該方法從容器中返回指定名稱的Bean。此外,BeanFactory接口的功能能夠經過實現它的接口進行擴展(好比ApplicationContext)。看下面的示例:

//咱們使用Spring配置文件爲User類提供配置信息,而後經過BeanFactory裝載配置文件,啓動Spring IoC容器。 
<?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="user" class="com.cad.domain.User"></bean>   
</beans>
// 咱們經過XmlBeanFactory實現類啓動Spring IoC容器 
public class Test {
    @org.junit.Test
    public void test(){ 
        //獲取配置文件
        ResourcePatternResolver  resolver=new PathMatchingResourcePatternResolver(); 
        Resource rs=resolver.getResource("classpath:bean.xml");

        //加載配置文件並啓動IoC容器
        BeanFactory bf=new XmlBeanFactory(rs);

        //從容器中獲取Bean對象
        User user=(User) bf.getBean("user");

        user.speak();
    }
}複製代碼

XmlBeanFactory裝載Spring配置文件並啓動IoC容器,經過BeanFactory啓動IoC容器時,並不會初始化配置文件中定義的Bean,初始化建立動做在第一個調用時。在初始化BeanFactory,必須提供一種日誌框架,咱們使用Log4J。

二、ApplicationContext

ApplicationContext由BeanFactory派生而來,提供了更多面向實際應用的功能。在BeanFactory中,不少功能須要編程方式來實現,而ApplicationContext中能夠經過配置的方式來實現。ApplicationContext的主要實現類是ClassPathXmlApplicationContextFileSystemXmlApplicationContext,前者默認從類路徑加載配置文件,後者默認從文件系統中加載配置文件,以下所示:

// 和BeanFactory初始化類似,ApplicationContext初始化也很簡單
ApplicationContext ac=new ClassPathXmlApplicationContext("bean.xml");複製代碼

ApplicationContext的初始化和BeanFactory初始化有一個重大的區別,BeanFactory初始化容器時並未初始化Bean,只有第一次訪問Bean時才建立;而ApplicationContext則在初始化時就實例化全部的單實例的Bean。所以,ApplicationContext的初始化時間會稍長一點。

三、WebApplicationContext

WebApplicationContext是專門爲Web應用準備的,它容許以相對於Web根目錄的路徑中加載配置文件完成初始化工做。從WebApplicationContext中能夠獲取ServletContext的引用,整個WebApplicationContext對象做爲屬性放置到ServletContext中,以便Web應用環境中能夠訪問Spring應用上下文。ConfigurableWebApplicationContext擴展了WebApplicationContext,容許經過配置方式實例化WebApplicationContext,定義了兩個重要方法。

  • setServletContext(ServletContext servletcontext):爲Spring設置ServletContext
  • setConfigLocation(String[] configLocations):設置Spring配置文件地址。

WebApplicationContext初始化的時機和方式是:利用Spring提供的ContextLoaderListener監聽器去監聽ServletContext對象的建立,當ServletContext對象建立時,建立並初始化WebApplicationContext對象。所以,咱們只須要在web.xml配置監聽器便可。

<!-- 利用Spring提供的ContextLoaderListener監聽器去監聽ServletContext對象的建立,並初始化WebApplicationContext對象 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- Context Configuration locations for Spring XML files(默認查找/WEB-INF/applicationContext.xml) -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>複製代碼

四、BeanFactory、ApplicationContext和WebApplicationContext的聯繫與區別

Spring經過一個配置文件描述Bean與Bean之間的依賴關係,經過Java語言的反射技術能實例化Bean並創建Bean之間的依賴關係。Spring的IoC容器在完成這些底層工做的基礎上,還提供了bean實例緩存、生命週期管理、事件發佈,資源裝載等高級服務。

  BeanFactory是Spring最核心的接口,提供了高級IoC的配置機制。ApplicationContext創建在BeanFactory的基礎上,是BeanFactory的子接口,提供了更多面嚮應用的功能。咱們通常稱BeanFactory爲IoC容器,ApplicationContext爲應用上下文,也稱爲Spring容器。WebApplicationContext是專門爲Web應用準備的,它容許以相對於Web根目錄的路徑中加載配置文件完成初始化工做,是ApplicationContext接口的子接口。

  BeanFactory是Spring框架的基礎,面向Spring自己;ApplicationContext面向使用Spring框架的開發者,幾乎全部的應用咱們都直接使用ApplicationContext而非底層的BeanFactory;WebApplicationContext是專門用於Web應用。

五、父子容器

  經過HierarchicalBeanFactory接口,Spring的IoC容器能夠創建父子層級關聯的體系:子容器能夠訪問父容器的Bean,父容器不能訪問子容器的Bean。

  Spring使用父子容器實現了不少功能,好比在Spring MVC中,控制器Bean位於子容器中,業務層和持久層Bean位於父容器中。但即便這樣,控制器Bean也能夠引用持久層和業務層的Bean,而業務層和持久層就看不到控制器Bean。


更多精彩文章,關注公衆號【ToBeTopJavaer】,更有數萬元精品vip資源免費等你來拿!!!複製代碼

相關文章
相關標籤/搜索