1. 程式人生 > >spring 基礎一

spring 基礎一

1 介紹一下spring:

  • spring管理你的業務物件,“一站式”解決方案,並貫穿表現層springmvc、業務層及持久層spring j dbc,與其他框架無縫結合。

  • Spring框架是一個為Java應用程式的開發提供了綜合、廣泛的基礎性支援的Java平臺。Spring幫助開發者解決了開發中基礎性的問題,使得開發人員可以專注於應用程式的開發。Spring框架本身亦是按照設計模式精心打造,這使得我們可以在開發環境中安心的整合Spring框架,不必擔心Spring是如何在後臺進行工作的。

  • Spring框架至今已集成了20多個模組。這些模組主要被分如下圖所示的核心容器、資料訪問/整合,、Web、AOP(面向切面程式設計)、工具、訊息和測試模組。

  • Spring是一個一站式的解決框架,對我們web開發當中的各個層級都有對應的解決方案。

2 spring的優缺點:

優點:高內聚低耦合
    1.方便解耦,簡化開發

sping就是一個大工廠,可以將所有的物件建立和依賴關係維護,交給sprong管理

    2.AOP程式設計的支援

Spring提供面向切面程式設計,可以方便的實現對程式進行許可權攔截,執行監控等功能

    3.宣告式事務的支援

只需要通過配置就可以完成對事務的管理,不用動手程式設計

    4.方便程式的測試

Spring對Junit4支援,可以通過註解方便的測試Spring程式

    5.方便整合各種優秀框架

Spring不排斥各種優秀的開源框架,其內部提供了對各種優秀框架(如: Struts, Hibernate, Mybatis, Quartz 等)的直接支援

    6.降低JavaEE API的使用難度

Spring對JAvaEE開發中非常難用的一些API (JDBC, javaMail,遠端協調_,都提供了封裝,是這些API應用難度大大降低

    7.IOC和DI

大大降低程式的耦合性,促進了低耦合,簡化了開發


  • 缺點:
    1.增加一定複雜度
    2.依賴spring容器重
    3. 配置檔案比較多,配置比較複雜

3 Spring的架構體系

spring的架構體系

Test:測試模組,spring可以與我們的junit進行整合做測試非常方便

Core  container :核心容器,就是用來裝javaBean物件。

AOP:切面程式設計

Aspects:切面程式設計應用的一個模組,與我們aop共同組成spring當中的切面程式設計

Data Access:資料訪問

Web:對資料訪問的支援

Transactions:用於支援我們的事物處理。用於解決我麼業務層的事物處理問題

Messaging: 訊息佇列

4 spring第一大特性 控制反轉 IOC : 建立物件

4.1 IOC:

inversion of controller 控制反轉,什麼是控制反裝:就是將建立物件的過程或者說建立物件的許可權交給了spring框架來幫我們處理,我們再不用通過new的方式來建立Javabean物件,這個過程就叫做控制反轉, 通過spring容器主動建立物件,就是通過反射來建立物件。

4.3 IOC與DI的區別與聯絡

  • IOC是建立我們的物件
  • DI就是為我們物件中的屬性賦值
  • DI依賴於IOC,只有我們先建立物件,才能個屬性賦值

5 spring第二大特性 DI 依賴注入: 給屬性賦值

DI:dependency injection 依賴注入,就是建立物件之後,給屬性賦值的過程就叫做DI,說白了就是通過配置來給屬性賦值

  • IOC與DI的關係:先建立物件,然後才有可能通過DI來進行賦值
  • DI是屬性賦值,依賴於物件的建立,也就是依賴於IOC。

5.1 第一種屬性賦值: 通過set 方法進行屬性賦值

屬性的型別一定要匹配

    <bean id = "date" class = "java.util.Date"></bean>

    <bean id = "dog" class = "com.hzh.demo4.Dog">
        <property name = "name" value = "金毛"></property>
        <property name = "age" value = "4"></property>
        <property name = "color" value = "紅色"></property>
    </bean>

    <bean id = "PersonProperty" class="com.hzh.demo4.Person">
        <property name="name" value = "張三"></property>
        <property name="age" value = "4"></property>
        <property name = "dog" ref = "dog"></property>
        <property name = "date" ref = "date"></property>
    </bean>

5.2 第二種屬性賦值: 通過構造器(有參)給屬性賦值

無參 有參 都給

    <bean id = "tom" class = "com.hzh.demo5.Tom">
        <constructor-arg name = "color" value = "藍色"></constructor-arg>
        <constructor-arg name = "name" value = "湯姆貓"></constructor-arg>
        <constructor-arg name = "age" value = "12"></constructor-arg>
        <constructor-arg name = "jerry" ref = "jerry"></constructor-arg>
    </bean>

    <bean id = "jerry" class = "com.hzh.demo5.Jerry">
        <constructor-arg name = "name" value = "小老鼠"></constructor-arg>
        <constructor-arg name = "age" value = "2"></constructor-arg>
    </bean>

5.3 給集合屬性 List 賦值

    <bean id = "collectProperty" class = "com.hzh.demo6.CollectProperty">
        <property name = "lists">
            <list>
                <value>張三</value>
                <value>list</value>
                <value>123</value>
                <value type = "java.lang.Integer">456</value>
                <value>"lisi"</value>
                <!--物件的引用-->
                <ref bean="tom"/>
            </list>
        </property>
    </bean>

5.4 給集合屬性 List 賦值

    <bean id = "collectProperty" class = "com.hzh.demo6.CollectProperty">
        <property name = "lists">
            <list>
                <value>張三</value>
                <value>list</value>
                <value>123</value>
                <value type = "java.lang.Integer">456</value>
                <value>"list"</value>
                <ref bean="tom"/>
            </list>
        </property>
        <property name="maps">
            <map>
                <entry key = "張三" value= "123"></entry>
                <entry key = "list" value-ref= "jerry"></entry>
                <!--字串 = 物件-->
                <entry key = "lists" value-ref= "tom"></entry>
                <!--字串 = 物件-->
                <entry key-ref = "jerry"  value-ref= "tom"></entry>
                <!--物件 = 字串-->
                <entry key-ref = "jerry" value= "王五"></entry>
            </map>
        </property>
    </bean>

5.5 給集合屬性 set 賦值

        </property>
            <property name="sets">
            <set>
                <value>張三</value>
                <value>123</value>
                <value>123</value>
                <ref bean="dog"/>
                <ref bean="dog"/>
            </set>
        </property>

5.6 給集合屬性Property賦值

        <!--注意properties的屬性賦值只能寫字串 -->
        <property name="properties">
            <props>
                <prop key="list">34</prop>
                <prop key="zhangsan">12</prop>
                <prop key="中國">首都北京</prop>
            </props>
        </property>

6 核心容器 Core container :核心容器,就是用來裝javaBean物件的容器。

spring容器

6.1 獲取容器的三種方式:

  • 1 使用ClassPathXmlApplicationContext獲取容器類,ApplicationContext 是我們容器的一個子介面
     ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    UserDao dao = (UserDao) context.getBean("userDao");
  • 2 XmlBeanFactory來獲取容器類,已過時
    XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
    UserDao dao = (UserDao) factory.getBean("userDao");
  • 3 使用FileSystemXmlApplicationContext來獲取容器,需要傳入spring配置檔案的絕對路徑
    可以使用外部的配置檔案
    FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("F:\\workspace_myProject\\springDemo\\src\\main\\resources\\applicationContext.xml");
    UserDao dao = (UserDao)context.getBean("userDao");

7 Java Bean

7.1 IOC 建立Java Bean 的三種方式

在配置檔案載入完成之後就會建立配置的全部的JavaBean,並且放入到容器中
注意: 在建立Java Bean物件的時候對物件進行初始化,執行初始化方法
  • 1 通過無參構造的方式建立:
    • 條件: 必須有無參構造
    <bean id = "createBean" class="com.hzh.springbean.UserBeanFactory">
    </bean>
  • 2 通過靜態工廠方式建立物件
    • factory-method :工廠類的靜態方法.必須用static修飾
    • 靜態方法必須有返回值
    • class: 工廠類的相對路徑
<   !-- 通過靜態工廠建立物件 -->
    <bean id = "userBean2Factory" class = "com.hzh.springbean.UserBeanFactory2" factory-method="getFactory"></bean>
  • 3 通過例項工廠獲取javaBean
    • 工廠類的方法不需要static修飾
    • factory-bean: 為工廠類物件
    • factory-method: 為工廠類的方法.
    • 第二個class : 返回物件類的相對路徑
    <!-- 通過例項工廠獲取javaBean -->
    <!-- 建立例項工廠 -->
    <bean id = "userBean3Factory" class ="com.hzh.springbean.UserBean3Factory" ></bean>
    <!-- 通過已經申明的工廠來獲取我們的javaBean物件 -->
    <bean  id = "userBean3" class = "com.hzh.springbean.UserBeanFactory2" factory-bean="userBean3Factory" factory-method="getBean2"></bean>

靜態工廠和例項工廠的區別就是方法有沒有靜態修飾

使用預設構造可以直接獲取某一個javaBean的物件
通過靜態工廠和例項工廠則可以一個工廠提供不同的JavaBean物件,只需要選擇相對應的工廠方法即可.

7.2 Spring Bean的作用域與作用範圍

Bean的作用域範圍有四種:

singleton 單列 預設 :

建立一個物件,每次呼叫,都使用這個物件
這種範圍確保不管接受到多少個請求,每個容器中只有一個bean的例項,單例的模式由bean factory自身來維護。

prototype 多例 :

每次呼叫都會建立一個新的例項 ,為每一個bean請求提供一個例項。

Request:

適用於web開發當中,將我們的物件儲存在request域中

Session:

適用於web開發當中,將我們的物件儲存在session中

7.3 java Bean 的生命週期

  • 可以配置init-method與destroy-method來實現bean的初始化和關閉的時候呼叫指定的方法

  • Spring Bean的生命週期簡單易懂。在一個bean例項被初始化時,需要執行一系列的初始化操作以達到可用的狀態。同樣的,當一個bean不在被呼叫時需要進行相關的析構操作,並從bean容器中移除。

    Spring bean factory 負責管理在spring容器中被建立的bean的生命週期。Bean的生命週期由兩組回撥(call back)方法組成。
    初始化之後呼叫的回撥方法。
    銷燬之前呼叫的回撥方法。

  • Spring框架提供了以下四種方式來管理bean的生命週期事件:

    • InitializingBean和DisposableBean回撥介面
      • 針對特殊行為的其他Aware介面
      • Bean配置檔案中的Custom init()方法和destroy()方法
      • @PostConstruct和@PreDestroy註解方式

      • 使用customInit()和 customDestroy()方法管理bean生命週期的程式碼樣例如下:

<bean id = "userDemo" class="com.hzh.User" init-method="initMethod" destroy-method="destoryMethod"></bean>

如果要銷燬一個方法,則使用 ClassPathXmlApplicationContext類的物件呼叫 .close()即可

7.4 BeanFactory和ApplicationContext有什麼區別?

  • ①ApplicationContext 介面繼承BeanFactory介面,Spring核心工廠是BeanFactory ,BeanFactory採取延遲載入,第一次getBean時才會初始化Bean, ApplicationContext是會在載入配置檔案時初始化Bean。

  • ②ApplicationContext是對BeanFactory擴充套件,它可以進行國際化處理、事件傳遞和bean自動裝配以及各種不同應用層的Context實現

    • ③從表面上看,application context如同bean factory一樣具有bean定義、bean關聯關係的設定,根據請求分發bean的功能。但application context在此基礎上還提供了其他的功能。

      • 提供了支援國際化的文字訊息
      • 統一的資原始檔讀取方式
      • 已在監聽器中註冊的bean的事件

7.5 Spring通過配置檔案和註解的方式建立javaBean物件的比較

  • 自己寫的java類,建議全部用註解的方式
  • Jar包中的類,全部用配置檔案的方式

8 spring 與 WEB的整合

8.1 Spring為什麼要與我們的javaWeb整合???

我們是從spring容器中取出物件,那麼我們每請求一個java Bean 物件,就要建立一個spring容器嗎?,每建立一個spring容器,就要在jvm中開闢出一塊空間,分配地址,這樣會浪費我們的jvm資源,我們可不可以讓spring容器之建立一次?

整合思路:在我們建立javaWeb容器的時候,就會建立一個ServletContext物件,並且這個物件是唯一的,單例的,直到javaWeb容器關閉的時候,才會銷燬。
那麼問題來了,我們可不可以監聽ServletContext的啟動,如果監聽到ServletContext的啟動,我們馬上就去啟動我們的spring容器,也就是說,ServletContext只啟動一次,我們的spring容器也只啟動一次,將spring容器啟動成功之後,就把我們的spring容器放到ServletContext物件當中,以後需要使用spring容器,再不用自己去new了,直接從ServletContext當中獲取即可

8.2 匯入jar

<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>4.2.4.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
</dependency>

8.3 監聽ServletContext的建立

  • 在WEB-INF下的web.xml中配置監聽器:
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext*.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

8.4 定義自己的servlet,在servlet請求中獲取spring容器

這裡寫圖片描述

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //1 獲取servletContext物件
        ServletContext servletContext = request.getServletContext();

        //2 從servletContext中取出spring容器,
        WebApplicationContext attribute = (WebApplicationContext) servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);

        //3 獲取javaBean物件
        Dog bean = (Dog) attribute.getBean("dog");
        System.out.println("小狗的名字: "+bean.getName());

        response.getWriter().append("Served at: ").append(request.getContextPath());
    }

8.5 設定訪問路徑,訪問

如果使用tomcat外掛,配置了 :

    <path>/</path>

則訪問時不用寫專案名: http://localhost:8080/ContextSerlvet



9 spring註解的使用

9.1 匯入jar包

<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>4.2.4.RELEASE</version>
</dependency>

9.2 開啟註解

    <!-- 開啟註解 -->
    <context:annotation-config></context:annotation-config>

9.3 開啟包掃描

    <!-- 包掃描 -->
    <context:component-scan base-package="com/hzh/demo8"></context:component-scan>

9.4 使用註解

/**
 * @Value("張三"):簡單型別的注入
 * 
 * @Autowired : 複雜屬性的注入,會直接去spring容器中找注入的物件,不用關心 (value = "?"),即不用考慮類的ID.
 * 
 * @Autowired+@Qualifier(value = "cat") :無論類名上面有沒有ID,(value = "?")必須有,類名有ID,?=類名ID,類名無ID,?=類名首字母小寫
 * 
 * @Resource : 可以寫ID,也可以不寫ID,
 *  
 * @Resource(name = "cat"): 如果寫ID,則要與我們類名的ID保持一致.
 */
  • @Component == @Controller == @Service [email protected]

  • @Controller 用於我們的資料展現層

  • @Service 用於我們的業務邏輯層

  • @Repository 用於我們的到層

  • @Value 用於我們簡單型別屬性的賦值



10 spring與junit的整合

10.1 匯入jar包

<!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>4.2.4.RELEASE</version>
    <scope>test</scope>
</dependency>

10.2 在我們的測試類上新增兩個註解,並且指定我們的配置檔案所在的位置

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "classpath:applicationContext-web.xml")