SSH框架之旅-spring(1)

spring.jpg

1.Spring 框架介紹


Spring 是一個開源的輕量級 Java 開發框架,可以解決業務邏輯層和其他層的耦合太高的問題,它不僅可以用在 Java EE 上,對于 Java SE 同樣可以使用。美其名曰,Spring 的出現算是給軟件開發帶來了春天,它的分層架構可以使 Spring 框架搭配其他的框架使用,如 Struts2,Hibernate,三者總稱為 SSH 框架。Spring 不僅僅是一個框架,控制反轉(IOC)和面向切面編程(AOP)的設計思想才是其精華所在。

Spring 中 Java EE 開發的三層結構:

  • web 層:Spring MVC
  • service 層:Bean 管理
  • dao 層:Spring 的 JDBCTemplate 整合其他持久層框架,如:Hibernate

2.spring 中的概念


2.1 AOP(面向切面編程)

這個在 Strust2 中也提到了,Struts2 的攔截器就是面向切面編程的一種實現方式,在原有的功能基礎上擴展功能不用修改源代碼,而是通過配置文件。

2.2 IOC(控制反轉)

將對象的創建權交給 Spring,而不是通過 new 的方式來創建對象,這樣也符合軟件開發中 高內聚低耦合 的設計理念,盡可能的降低對象與對象之間的調用關系。

3.搭建 Spring 框架

3.1 準備 Spring 的相關 jar 包

在 Spring 框架的官網上,下載按鈕并不是在顯眼的位置,這里提供一個 Spring 各個版本 下載地址,我下載的是 4.3.9 版本的 zip 壓縮包。解壓后,docs 文件夾是 Spring 的 API 文檔和開發規范,libs 文件夾 是 Spring 的 jar 包和源碼,scheme 文件夾 是 Spring 的約束文件。在 libs 文件夾內,每三個 jar 包是一組,包括開發用的 jar 包,說明文檔,源碼。

3.2 導入 Spring 的相關 jar 包

libs文件夾下的 spring-beans,spring-context,spring-core,spring-expression 這四個 jar 包,還有一個記錄日志的 jar 包 commons-logging,這個 jar 包不導入的話在控制臺會出現 java.lang.ClassNotFoundException 的錯誤,但這個包并不是 Spring 框架中的,屬于 Apache 項目中的一個開發組件,這里也提供一個 下載地址,在 java web項目中的lib文件夾下導入這五個 jar 包。

3.3 Spring 的使用案例

實體類

    package cc.wenshixin.entity;
    
    public class Student {
        
        public void study()
        {
            System.err.println("學習中。。。");
        }
    }

配置文件

Spring 的配置文件的名稱和位置不是固定的,但建議直接放在 src 目錄下便于和其他框架的配置文件統一管理,另外官方建議的配置文件名是 applicationContext.xml,但也可以自己設定配置文件名稱。和 Struts2、Hibernate 框架中的配置文件的約束文件類型不同,前兩者是 dtd 約束,而后者是 scheme 約束。關于scheme的約束模板,可以在這個 地址 (在靠后的部分)上找,也可以抄下面基本的模板約束。

    <?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="student" class="cc.wenshixin.entity.Student"></bean>
    </beans>

測試類

使用IOC(控制反轉)技術(在下面會詳細介紹IOC的底層實現原理),對象創建的工作就交給 Spring 來完成,加上類在配置文件中的 id 名就可以返回創建的對象,這里面是工廠模式的設計思想。

    package cc.wenshixin.test;
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import cc.wenshixin.entity.Student;
    
    public class Test1 {
        
        @Test
        public void test01()
        {
            //1.加載spring的配置文件,根據配置文件來創建對象
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            //2.得到配置中創建的對象
            Student student = (Student) context.getBean("student");
            student.study();
        }
    }

4.Spring 中的 bean 管理


4.1 IOC 的底層實現原理

IOC 的底層是通過 dom4j 解析 xml 文件、工廠設計模式,反射機制實現的,如下圖所示。

IOC底層原理.png

4.2 bean 實例化對象的三種方式

- 第一種 使用類的無參構造方法創建(重點)

上面的使用案例中就是使用的這種創建對象方式,比較簡單,在開發中經常使用。注意在實體類中要有無參數的構造函數,否則 Spring 無法創建實體類對象,出現異常。如果在實體類中有有參數的構造函數,要手動補上無參數的構造方法,來方便 Spring 的調用。

  • 第二種 使用靜態工廠創建

使用一個工廠類,創建靜態的方法,返回對象

實體類代碼同上

工廠類

    package cc.wenshixin.factory;
    
    import cc.wenshixin.entity.Student;
    
    public class StudentFactory1 {
        public static Student getStudent()
        {
            return new Student();
        }
    }

配置文件

  <!-- 使用靜態工廠創建 -->
  <bean id="studentFactory1" class="cc.wenshixin.factory.StudentFactory1" factory-method="getStudent"></bean>

測試類

    @Test
    public void test02()
    {
        //1.加載spring的配置文件,根據配置文件來創建對象
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //2.得到配置中創建的對象
        Student student = (Student) context.getBean("studentFactory1");
        student.study();
    }
  • 第三種 使用實例工廠創建

使用一個工廠類,創建普通的方法,返回對象

實體類代碼同上

工廠類代碼

    package cc.wenshixin.factory;
    
    import cc.wenshixin.entity.Student;
    
    public class StudentFactory2 {
        public Student getStudent()
        {
            return new Student();
        }
    }

配置文件

  <!-- 使用實例工廠創建 -->
  <bean id="studentFactory2" class="cc.wenshixin.factory.StudentFactory2"></bean>
  <bean id="stud" factory-bean="studentFactory2" factory-method="getStudent"></bean>

測試類

    @Test
    public void test03()
    {
        //1.加載spring的配置文件,根據配置文件來創建對象
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //2.得到配置中創建的對象
        Student student = (Student) context.getBean("stud");
        student.study();
    }

4.3 bean 標簽中的常用屬性

  • id 屬性:給 bean 起名字,id 屬性名稱可以任意,但不能包含特殊符號,用于根據 id 屬性值得到配置對象。
  • class 屬性:創建對象所在類的全路徑
  • name 屬性:功能和 id 屬性一樣,但 name 屬性名稱中可以包含特殊符號
  • scope 屬性:
    • 1.singleton 屬性默認值,單個對象
    • 2.prototype 多個對象
    • 3.request 創建對象并把對象放在 request 域中
    • 4.session 創建對象并把對象放在 session 域中
    • 5.globalSession 創建對象并把對象放在 globalSession 中

scope屬性的前兩個屬性值常用,后面幾個知道即可.

測試 singleton 屬性值,默認的可以不寫,修改上面測試類中的代碼如下:

    @Test
    public void test01()
    {
        //1.加載spring的配置文件,根據配置文件來創建對象
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //2.得到配置中創建的對象,使用單例模式,兩個對象引用的地址相同
        Student s1 = (Student) context.getBean("student");
        Student s2 = (Student) context.getBean("student");
        System.out.println(s1);
        System.out.println(s2);
    }

測試 prototype 屬性值,修改配置文件的代碼如下:

    <bean id="student" class="cc.wenshixin.entity.Student" scope="prototype"></bean>

再次執行上面的測試類代碼,觀察兩個對象引用的地址不同,即創建了多個對象。

4.3 bean 中屬性注入

所謂屬性注入就是在創建類對象時向對象的屬性中設置值,名字起的有些高大上。

一般屬性注入有三種方式

  • 1.使用 set 方法注入
    public class Student{
      private String name;
      public setName(String name){
        this.name = name
      }
    }
    //set方法注入
    Student student = new Student();
    student.setName("小明");
  • 2.使用有參構造函數注入
    public class Student{
      private String name;
      public Student(String name){
        this.name = name
      }
    }
    //構造函數注入
    Student student = new Student("小明");
  • 3.使用接口注入
public interface Dao{
  public void setName(String name);
}
public class DaoImpl implements Dao{
  private String name;
  public void setName(String name){
    this.name = name;
  }
}

但在 Spring 中,只支持前兩種方式,也即是 set 方法注入和構造函數注入,通過配置文件來是使對象被創建時給對象的相關屬性賦值。

- 使用 set 方法注入屬性

修改實體類為

    package cc.wenshixin.entity;
    
    public class Student {
        private String name;

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

配置文件

  <!-- 使用方式注入屬性 -->
  <bean id="student" class="cc.wenshixin.entity.Student">
    <property name="name" value="小明"></property>
  </bean>

測試方法

    @Test
    public void test01()
    {
        //1.加載spring的配置文件,根據配置文件來創建對象
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //2.得到配置中創建的對象
        Student s = (Student) context.getBean("student");
        //輸入配置文件中注入的屬性值
        System.out.println(s.getName());
    }
  • 使用有參構造函數注入屬性

實體類增加有參構造方法

配置文件修改為

  <!-- 使用有參構造函數注入屬性 -->
  <bean id="student" class="cc.wenshixin.entity.Student">
    <!-- 使用有參構造注入 -->
    <constructor-arg name="name" value="小紅"></constructor-arg>
  </bean>

測試方法同上

  • 注入對象類型的屬性

創建一個 servic 類和 dao 類,在 service 中得到 dao 的對象,這在 Java Web 開發中是很常見的。

示例代碼如下:

實體類同上

dao 類

    package cc.wenshixin.entity;
    
    public class Dao {
        public void insert()
        {
            System.out.println("Dao插入學生數據。。。");
        }
    }

service 類

    package cc.wenshixin.entity;
    
    public class Service {
        //定義到類型屬性
        private Dao dao;
        //生成set方法
    
        public void setDao(Dao dao) {
            this.dao = dao;
        }
        
        public void add()
        {
            System.out.println("Service添加操作");
            dao.insert();
        }
    }

配置文件

property 標簽中,name 屬性值為 service 類中的屬性名稱,ref 屬性值為dao中配置中 id 屬性值,這里就不能寫 value 屬性了,因為是一個對象,無法屬性注入。

  <!-- 配置service和dao對象 -->
  <bean id="dao" class="cc.wenshixin.entity.Dao"></bean>
  <bean id="service" class="cc.wenshixin.entity.Service">
    <property name="dao" ref="dao"></property>
  </bean>

測試方法

    @Test
    public void test03()
    {
        //1.加載spring的配置文件,根據配置文件來創建對象
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //2.得到配置中創建的對象
      Service service = (Service) context.getBean("service");
      service.add();
    }
  • P 名稱空間屬性注入

在配置文件的約束中加上 xmlns:p="http://www.springframework.org/schema/p"

實體類中需要默認的構造函數和屬性對應的set方法

package cc.wenshixin.entity;

public class Student {
    private String name;
    
    public Student() {

    }

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

配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            注釋:加上p名稱空間
            xmlns:p="http://www.springframework.org/schema/p"
            xsi:schemaLocation="
                    http://www.springframework.org/schema/beans
                    http://www.springframework.org/schema/beans/spring-beans.xsd">
       <!-- p名稱空間注入 -->
       <bean id="student" class="cc.wenshixin.entity.Student" p:name="老王"></bean>
    </beans>

測試方法

    @Test
    public void test01()
    {
        //1.加載spring的配置文件,根據配置文件來創建對象
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //2.得到配置中創建的對象
        Student s = (Student) context.getBean("student");
        System.out.println(s.getName());
    }
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,908評論 18 139
  • Spring Boot 參考指南 介紹 轉載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,948評論 6 342
  • (一)Struts、Spring、Hibernate、Mybatis框技術 1.Struts2.0有幾種標簽庫 【...
    獨云閱讀 3,275評論 0 62
  • 第一案:秘密花園 每日更新一到兩篇 1.初見露西 2.案發現場 3.巧妙推理 4.真相大白 這天,天氣晴朗,...
    神犬小露西閱讀 420評論 0 1
  • 逃離,地獄之門 在漫無邊際的森林里 尋找,重生的出路 混淆不清的記憶 看不見的渾濁世界 迫使我,再一次陷入 模糊的...
    一泓夜雨閱讀 214評論 2 2