深入學習Spring框架(一)- 入門

ki16發表於2019-07-12

1.Spring是什麼?

  Spring是一個JavaEE輕量級的一站式開發框架。
    JavaEE: 就是用於開發B/S的程式。(企業級)
    輕量級:使用最少程式碼啟動框架,然後根據你的需求選擇,選擇你喜歡的模組使用。
    重量級:早期有的EJB,開發一個HelloWorld程式都需要引入EBJ的全部模組
    一站式:Spring框架提供涵蓋了JavaEE開發的表示層,服務層,持久層的所有元件功能。也就是說,原則上,學完一套Spring框架,不用其他框架就可以完成網站一條流程的開發。但是Spring仍然可以和其他的框架無縫整合。

2.Spring的優點

  輕量:Spring 是輕量的,就是除核心模組(4個jar),其他模組由開發者自由選擇使用,同時支援整合其他框架。也可以稱為就是可插拔式開發框架,像插頭和插座一樣,插上就用。這就是Spring框架核心理念(Ioc)。
  控制反轉:Spring通過控制反轉實現了鬆散耦合,物件們給出它們的依賴,而不是建立或查詢依賴的物件們。
  面向切面的程式設計(AOP):Spring支援面向切面的程式設計,並且把應用業務邏輯和系統服務分開。
  容器:Spring 包含並管理應用中物件的生命週期和配置。
  MVC框架:Spring的WEB框架是個精心設計的框架,是Web框架的一個很好的替代品。
  事務管理:Spring 提供一個持續的事務管理介面,可以擴充套件到上至本地事務下至全域性事務(JTA)。
  異常處理:Spring 提供方便的API把具體技術相關的異常(比如由JDBC,Hibernate or JDO丟擲的)轉化為一致的unchecked 異常。

3.Spring的作用

  Spring強調的理念是,輕量級。Spring的輕量級主要體現在模組的可插拔,Spring提供的功能模組,除了核心模組以外,開發人員可以選擇性使用。所以,Spring框架在現實開發中,主要的功能用於整合各種開發框架開發專案。

 

4.Spring框架包

  Spring官方網站:https://spring.io/

  4.1 下載

  Spring官方提供的Maven方式的專案下載:https://start.spring.io/
  但是基於簡單入門的原則,我們要通過匯入包的方式來學習。需要下載框架的zip包
  地址為:http://repo.springsource.org/libs-release-local/org/springframework/spring/

  4.2 目錄說明

  根目錄:

  

  jar包:

  

  包說明:

包名 說明
spring-aop-4.3.2.RELEASE.jar 實現了AOP的支援
spring-aspects-4.3.2.RELEASE.jar AOP框架aspects支援包
spring-beans-4.3.2.RELEASE.jar 核心支撐包,實現了處理基於xml物件存取
spring-context-4.3.2.RELEASE.jar  核心支撐包,實現了Spring物件容器
spring-context-support-4.3.2.RELEASE.jar  容器操作擴充套件包,擴充套件了一些常用的容器物件的設定功能
spring-core-4.3.2.RELEASE.jar  核心支撐包,Spring的核心
spring-expression-4.3.2.RELEASE.jar  核心支撐包,實現了xml對Spring表示式的支援
spring-instrument-4.3.2.RELEASE.jar  提供了一些類載入的的工具類
spring-instrument-tomcat-4.3.2.RELEASE.jar  提供了一些tomcat類載入的的工具類,實現對應Tomcat服務的呼叫
spring-jdbc-4.3.2.RELEASE.jar  SpringJDBC實現包,一個運算元據庫持久層的子框架
spring-jms-4.3.2.RELEASE.jar  整合jms的支援,jms:Java訊息服務。
spring-messaging-4.3.2.RELEASE.jar  整合messaging api和訊息協議提供支援
spring-orm-4.3.2.RELEASE.jar  ORM框架整合包,實現了Hibernate,IBatis,JDO的整合。
spring-oxm-4.3.2.RELEASE.jar  Spring OXM對主流O/X Mapping框架做了一個統一的抽象和封裝。就是對應XML讀寫框架的支援
spring-test-4.3.2.RELEASE.jar  Spring整合JUnit測試
spring-tx-4.3.2.RELEASE.jar  事務代理的支援
spring-web-4.3.2.RELEASE.jar  SpringWeb通用模組
spring-webmvc-4.3.2.RELEASE.jar  SpringMVC子框架
spring-webmvc-portlet-4.3.2.RELEASE.jar  Spring對門戶技術(portlet)的支援
spring-websocket-4.3.2.RELEASE.jar  Spring對websocket的支援

注:紅色部分為基礎核心包,使用Spring必須匯入

 

5.入門例項

  Spring之所以可以實現模組的可插拔是支援依賴注入,所謂的依賴注入/控制反轉就是不用new就可以建立物件。

  使用Spring框架不用new建立一個物件:

  1.建立專案並匯入jar包:將Spring的基礎支撐包和依賴的日誌包複製到lib檔案下,並且加入專案中

  

  2.建立配置檔案
  在專案的src下面建立配置檔案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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
 
 
</beans>

  3.建立物件到Spring容器中
  建立一個類

package com.gjs.service;

public class HelloSpringService {
    public void say() {
        System.out.println("你好!Spring");
    }
}

  往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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
         <!-- <bean id="" class = ""> 
          配置讓spring管理類的物件的建立
          id : 唯一標識
          class :被管理類的全限定名
          -->  
        <bean id="HelloSpringService" class="com.gjs.service.HelloSpringService"/>
            
</beans>

  測試類, 使用getBean方法獲得容器中的物件。

package com.gjs.test;

import static org.junit.Assert.*;

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

import com.gjs.service.HelloSpringService;

public class TestSpring {
    @Test
    public void testName() throws Exception {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        HelloSpringService helloSpringService = context.getBean("HelloSpringService",HelloSpringService.class);
        helloSpringService.say();
    }
}

6.Spring容器的兩個實現

ClassPathXmlApplicationContext:通過classpath路徑(相對路徑)直接獲得載入的xml檔案(推薦使用)

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

FileSystemXmlApplicationContext:通過檔案路徑(絕對路徑)來獲得載入的xml檔案。

ApplicationContext context = new FileSystemXmlApplicationContext("D:\\java\\eclipse-workspace\\spring1\\src\\applicationContext.xml");

8.控制反轉(IOC)和依賴注入(DI)(A)

  DI:Dependency Injection(依賴注入):

  依賴注入是指Spring建立物件的過程中,將物件依賴屬性(簡單值,集合,物件)通過配置設值給該物件。

  IoC:Inverse of Control(控制反轉):

  Spring號稱是一個可以實現模組可插拔的JavaEE開發框架。而實現程式可插拔的核心理念就是控制反轉。所謂的控制反轉,就是將程式碼的呼叫權從呼叫方轉移給被呼叫方(服務提供方)。不用修改呼叫方的的程式碼,只要修改配置檔案就實現物件的切換。
  讀作“反轉控制”,更好理解,它不是什麼技術,而是一種設計思想,好比於MVC。就是將原本在程式中手動建立物件的控制權,交由Spring框架來管理。
  正控:若呼叫者需要使用某個物件,其自身就得負責該物件的建立。
  反控:呼叫者只管負責從Spring容器中獲取需要使用的物件,不關心物件的建立過程,也就是把建立物件的控制權反轉給了Spring框架。
  控制反轉(Ioc),就是依賴注入加上面向介面的程式設計思想的實現

  示例:

  整體結構:

  

  CustomService介面:

package com.gjs.service;

public interface CustomeService {
    public void say();
}

  實現類CustomServiceImpl1:

package com.gjs.service.impl;

import com.gjs.service.CustomeService;

public class CustomServiceImpl1 implements CustomeService {

    @Override
    public void say() {
        System.out.println("CustomerServiceImpl1.say()");
    }
}

  實現類CustomServiceImpl2:

package com.gjs.service.impl;

import com.gjs.service.CustomeService;

public class CustomServiceImpl2 implements CustomeService {

    @Override
    public void say() {
        System.out.println("CustomerServiceImpl2.say()");
    }
}

  呼叫方 CustomClient:

package com.gjs.client;

import com.gjs.service.CustomeService;

public class CustomClient {
    //1.宣告一個介面引用型別
    private CustomeService customeService;
    //2.spring的依賴注入(DI)需要有一個set方法
    public void setCustomeService(CustomeService customeService) {
        this.customeService = customeService;
    }
    
    public void say() {
        customeService.say();
    }
}

  配置檔案 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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
         <!-- 
        <bean id="" class = ""> 
          配置讓spring管理類的物件的建立
          id : 唯一標識
          class :被管理類的全限定名
          -->  
        <bean id="client" class="com.gjs.client.CustomClient">
            <!-- 依賴注入(DI) :注入被呼叫方 
              <property name="" value/ref=""/>
                         位置:
                  name : 是set方法確定的屬性,不是成員變數
                      確定屬性 : setXxx 方法去掉set字首 ,剩餘部分首字母小寫
                         引數:        
                  value : 值型別注入(字串,基本資料型別)
                  ref :引用資料型別(物件), 對應bean的id
           -->
            <property name="customeService" ref="ServiceImpl1"/>
        </bean>
        
        <bean id="ServiceImpl1" class="com.gjs.service.impl.CustomServiceImpl1"/>
        <bean id="ServiceImpl2" class="com.gjs.service.impl.CustomServiceImpl2"/>    
</beans>

  測試類:

package com.gjs.test;

import static org.junit.Assert.*;

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

import com.gjs.client.CustomClient;
import com.gjs.service.CustomeService;

public class TestSpring {
    @Test
    public void testName() throws Exception {
        //1.讀取配置檔案,建立Spring容器
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //獲取呼叫方 CustomClient物件
        CustomClient client = context.getBean("client", CustomClient.class);
        //呼叫CustomClient物件的say()方法
        client.say();
    }
}

  應用:

  Spring框架又被稱為容器框架,即通過控制反轉將各個框架的物件建立交給Spring管理,然後通過依賴注入在層之間傳遞引數整合框架,並達到低耦合的目的。

  

9.標籤說明

  9.1 bean標籤

  作用:用於宣告一個類,在啟動Spring框架的時候根據該配置的類建立物件到容器裡面

<bean id="someBean" class="com.gjs.pojo.SomeBean" scope="prototype"></bean>

id:設定物件名(唯一識別符號)(推薦使用)
name:設定物件名(唯一識別符號),與id的區別是可以有多個名稱,每個名稱用逗號隔開。
class:指定物件對應的類
scope:用於設定的物件的作用範圍,可選引數如下:

  

在Web開發的三層架構中的使用
  Web層:一般都是多例
  Service層 :單例
  DAO層 :單例

  9.2 alias 別名標籤  

  作用:為已配置的bean設定別名

bean id="user" name="test" class="com.gjs.pojo.User"/>
<alias name="user" alias="user1"/> 

name:必要屬性, 代表為哪一個bean配置別名, 此屬性的值為其他bean標籤的id或name屬性值
alias: 必要屬性,命名的別名

10.例項化Bean的四種方式

  1.構造器例項化(無引數構造器):(最常用)

public class SomeBean {
    public SomeBean() {
        System.out.println("SomeBean.SomeBean()");
    }
}
<bean id="someBean" class="com.gjs.pojo.SomeBean"/>

  2.通過靜態方法工廠建立(C)

public class SomeBean {
    public SomeBean() {
        System.out.println("SomeBean.SomeBean()");
    }
}
public class SomeBeanFacotry {
    //靜態工廠方法
    public static SomeBean getSomeBean() {
        System.out.println("執行靜態工廠方法");
        return new SomeBean();
    }
}
<bean id="someBean" class="com.gjs.pojo.SomeBeanFacotry" factory-method="getSomeBean"/>

  3.通過實體工廠建立(C)

public class SomeBean {
    public SomeBean() {
        System.out.println("SomeBean.SomeBean()");
    }
}
public class SomeBeanFacotry {
    //例項工廠方法
    public SomeBean getSomeBean() {
        System.out.println("執行例項工廠方法");
        return new SomeBean();
    }
}
<bean id="someBeanfactory" class="com.gjs.pojo.SomeBeanFactory"/>

<bean id="someBean" factory-bean="someBeanfactory" factory-method="getSomeBean"/>

  4.實現FactoryBean介面例項化:例項工廠變種
  實現FactoryBean介面,MyBatis和Spring整合就是使用的這種方式。此種方式,如果沒有使用Bean對應的物件,Spring就不會自動建立,只有在使用的時候Spring才會建立對應的物件

public class SomeBean {
    public SomeBean() {
        System.out.println("SomeBean4.SomeBean4()");
    }
}
public class SomeBeanObjectFactory implements FactoryBean<SomeBean>{
    //返回的泛型型別對應的物件
    @Override
    public SomeBean getObject() throws Exception {
        SomeBean bean = new SomeBean();
        return bean;
    }
}
<bean id="someBean" class="cn.zj.domian.SomeBeanObjectFactory"/>

11.初始化和銷燬方法

<bean id="someBean" class="......" 
   <init-method="該類中初始化方法名"/> 
  <destroy-method="該類中銷燬方法名"/>
</bean>

  init-method:bean生命週期初始化方法,物件建立後就進行呼叫
  destroy-method:容器被銷燬的時候,如果bean被容器管理,會呼叫該方法。

12.依賴注入的四種方法

  1.setter注入,(屬性注入)(常用)

使用setter注入:

1,使用bean元素的<property>子元素設定;

1.簡單型別值,直接使用value賦值;
2.引用型別,使用ref賦值;
3.集合型別,直接使用對應的集合型別元素即可。

2,spring通過屬性的set方法注入值;
3,在配置檔案中配置的值都是string,spring可以自動的完成型別的轉換

示例:

員工類

public class Employee {
    private Integer age;
    private String name;
    private Department dept;
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Department getDept() {
        return dept;
    }
    public void setDept(Department dept) {
        this.dept = dept;
    }
    @Override
    public String toString() {
        return "Employee [age=" + age + ", name=" + name + ", dept=" + dept + "]";
    }    
}

  部門類

public class Department {
    private Integer id;
    private String name;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = 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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <!-- 員工 -->
    <bean id="employee" class="com.gjs.pojo.Employee" >
        <!-- setter方法注入: 屬性注入 
            <property name="" value="">
            name : 屬性名稱
            value : 基本資料型別+String型別的值注入
            ref : 引用型別(物件型別)的注入
            value 和ref 只能二選一
        -->
        <property name="age" value="18"></property>
        <property name="name" value="張三"></property>
        <property name="dept" ref="dept"></property>
    </bean>
    <!-- 部門 -->
    <bean id="dept" class="com.gjs.pojo.Department" >
           <property name="id" value="1"/>
           <property name="name" value="開發部"/>
   </bean>
</beans>

2.構造器注入

使用bean元素的<constructor-arg>子元素設定:

1.預設情況下,constructor-arg的順序就是構造器引數的順序
2. constructor-arg的屬性

name : 構造方法引數的名稱
index :引數的位置從 0 開始
value :值型別注入
ref :引用型別注入
type : 引數的資料型別

3.一般在一個類必須依賴另一個類才能正常執行時,才用構造器注入

 

<?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="department" class="com.gjs.pojo.Department">
         
         <constructor-arg name="id"  value="2"/>
         <constructor-arg name="name"  value="研發部"/>
     </bean>
     
     <!-- 配置員工 -->
     <bean id="emp" class="com.gjs.pojo.Employee">
         <!-- 依賴注入 :構造器注入 -->
         <constructor-arg name="id" value="1"/>
         <constructor-arg name="name" value="張三"/>
         <constructor-arg name="dept" ref="department"/>
     </bean>
</beans>

  3.p名稱空間注入

  使用p名稱空間注入先在約束上面引入 p標籤
  xmlns:p="http://www.springframework.org/schema/p"

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:p="http://www.springframework.org/schema/p"
    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="department" class="com.gjs.pojo.Department" 
     p:id="3"
     p:name="銷售部"/>
     
     <!-- 配置員工 -->
     <bean id="emp" class="com.gjs.pojo.Employee" 
     p:id="1"
     p:name="張三"
     p:dept-ref="department"/>
</beans>

4.集合型別值注入
用於處理:
  1.鍵值對 Map 、Properties
  2.陣列
  3.集合Set、List

public class CollectionBean {
    private Set<String> set;
    private List<String> list;
    private String[] array;
    private Map<String, String> map;
    private Properties prop; //讀取本地 xxx.properties檔案(本質就是一個Map集合)
}
<?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="collectionBean" class="cn.zj.spring.pojo.CollectionBean">
         
         <!-- setter(屬性)方法注入 -->
         <!-- 1.陣列 -->
         <property name="arr">
             <array>
                 <value>AAA</value>
                 <value>BBB</value>
             </array>
         </property>
         
         <!-- 2.set集合 -->
         <property name="set" >
             <set>
                 <value>AAA</value>
                 <value>AAA</value>
                 <value>BBB</value>
             </set>
         </property>
         
         <!-- 3.list集合 -->
         <property name="lsit">
             <list>
                 <value>list1</value>
                 <value>list1</value>
                 <value>list2</value>
             </list>
         </property>
         <!-- 4. map集合 -->
         <property name="map">
             <map>
                 <entry key="key1" value="value1"/>
                 <entry key="key2" value="value2"/>
             </map>
         </property>
         <!-- 5.properties 集合 -->
         <property name="prop">
             <props>
                 <prop key="propKey1">propValue1</prop>
                 <prop key="propKey2">propValue2</prop>
             </props>
         </property>
     </bean> 
</beans>

13.獲得properties檔案的值

  1.匯入名稱空間方法
  將名稱空間和約束重新拷貝一份,將對於的全部替換成 context,然後關聯context本地schema約束

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    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
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    ">
    
</beans>

  2.匯入Mysql驅動包和druid連線池jar包

  

  3.applicationContext.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    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
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        ">
        
      <!-- 使用context 讀取配置檔案到spring容器中
         <context:property-placeholder location=""/>
         location : db.properties檔案的位置,必須加上 classpath: 作為字首
    -->
      <context:property-placeholder location="classpath:db.properties"/>
          <!-- 建立阿里巴巴druid連線池 -->
          <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" 
              init-method="init" destroy-method="close"
          >
              <!-- 屬性注入 setter方法注入-->
              <property name="driverClassName" value="${jdbc.driverClassName}"/>
            <property name="url" value="${jdbc.url}"/>
            <property name="username" value="${jdbc.username}"/>
            <property name="password" value="${jdbc.password}"/>
            <!-- 最大連線數 -->
            <property name="maxActive" value="${jdbc.maxActive}"/>
      </bean>
  
</beans>

  測試程式碼

@Test
    public void testSave() throws Exception {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        
        DataSource dataSource = context.getBean(DataSource.class, "dataSource");
        Connection conn = dataSource.getConnection();
        System.out.println("資料庫連線物件:"+conn);
    }

 

相關文章