1. 程式人生 > 其它 >Spring-01

Spring-01

內容

  • Spring概念
  • Spring快速入門
  • Spring的IoC 和 DI
  • Bean基本配置
  • Bean生命週期
  • Bean例項化
  • Bean注入

1. Spring概念

1.1 概念

  • Spring是分層的JavaSE/EE應用 full-stack輕量級開源框架

1.2 Spring全家桶

目前學習的是Spring Framework,是Spring全家桶的基礎。

1.3 Spring體系

  • Spring體系結構圖

  • SSM的提供的解決方案

    • MybatisDao層框架
    • SpringMVCweb層框架
    • Spring:軟體三層中都可以看到Spring的應用場景

1.4 發展歷程

  • Spring之父 Rod Johnson
  • EJB Enterprise Java Beansun公司提出來的大型web專案的架構
  • Expert One-on-One J2EE Design and Development 2002年 手把手教你怎麼使用EJB開發大型web專案
  • Expert one-on-one J2EE Development without EJB 2004 手把手教你怎麼不使用EJB開發大型web專案 (Spring的原型)
  • 官網:https://spring.io/projects
  • 課堂版本5.x

1.5 Spring優勢

  • 方便解耦,簡化開發

  • 方便整合各種優秀框架(不排斥、慢慢整合)

  • AOP(面向切面程式設計)程式設計的支援

  • 宣告式事務的支援

  • Java原始碼是經典學習範例

  • 方便程式的測試(Spring整合junit)

1.6 Spring兩大核心思想

  • IoC:Inverse of Control 控制反轉 ,目的:解耦

  • AOP:Aspect Oriented Programming 面向切面程式設計

  • Spring演化過程

    基於介面程式設計servicedao之間高度耦合

    工廠+配置檔案:解除了耦合,留下配置檔案和dao/工廠耦合,這種耦合是我們期望的一種耦合方式

  • IoC 控制反轉

  • Inverse of Control

    把物件的建立權、依賴的注入權從程式設計師手中,反轉到了Spring容器建立並提供

2. Spring quick Start

2.0 準備工作:配置私服

<!--  略  -->

2.1 IOC實現步驟

  1. 匯入Spring依賴座標:spring-context-5.2.10.RELEASE
  2. 編寫service/dao介面和實現類
  3. Spring核心配置檔案中配置service/dao實現類
  4. 測試類中建立Spring容器物件,並通過物件獲取service/dao實現類物件
  5. 呼叫service/dao實現類物件的方法測試

2.1.1 配置依賴座標

新建模組/匯入模組

<dependencies>
    <!--
        配置Spring的依賴座標
        會根據依賴傳傳遞自動匯入其依賴的其他座標
     -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.10.RELEASE</version>
    </dependency>
</dependencies>

2.1.2 編寫service/dao實現類和介面

BookDao.java介面

package com.cy.dao;

public interface BookDao {
    public void save();
}

BookDaoImpl.java實現類

package com.cy.dao.impl;

import com.cy.dao.BookDao;

public class BookDaoImpl implements BookDao {
    public void save() {
        System.out.println("book dao save ...");
    }
}

BookService介面

package com.cy.service;

public interface BookService {
    public void save();
}

BooKServiceImpl實現類

package com.cy.service.impl;

import com.cy.dao.BookDao;
import com.cy.dao.impl.BookDaoImpl;
import com.cy.service.BookService;

public class BookServiceImpl implements BookService {

    private BookDao bookDao = new BookDaoImpl();

    public void save() {
        System.out.println("book service save ...");
        bookDao.save();
    }
}

2.1.3 新建Spring的配置檔案並配置

resources 右鍵 選擇 new--》xml configration file --》Spring config(前提是Spring的依賴已經成功匯入)

配置檔名稱任意,習慣寫法applicationcontext.xml。本案中使用beans.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裝配進Spring容器
        id 唯一標識,任意起名,但是儘量使用提示的名字
        class  全限定類名(用於反射建立物件)
		小提示:先寫class,只寫類名有提示;再寫id,也有提示
     -->
    <bean id="bookDao" class="com.cy.dao.impl.BookDaoImpl"/>

    <bean id="bookService" class="com.cy.service.impl.BookServiceImpl">
  
</beans>

2.1.4 建立Spring容器物件並獲取bean物件

/**
 * @Description: 測試Spring容器建立和獲取物件
 */
package com.cy;

import com.cy.dao.BookDao;
import com.cy.service.BookService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App2 {
    public static void main(String[] args) {
        //3.獲取IoC容器
        ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
        //4.獲取bean(根據bean配置id獲取)
//        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
//        bookDao.save();

        BookService bookService = (BookService) ctx.getBean("bookService");
        bookService.save();

    }
}

2.2 DI實現步驟

2.2.1 DI概念

全稱:Dependency InjectionService用到daoService就依賴了Dao,就需要把Dao注入到Service中。

之前的注入方式:

  • 之前Service中的dao都是我們自己new的;

使用Spring中的依賴注入

  • 我們就不需要自己newSpring會自動找到(建立)Dao物件,並設定給Service中的成員變數。

2.2.2 實現步驟

  1. 基於IoC快速入門程式碼,完成下面操作。
  2. 刪除被依賴物件的new建立程式碼,並提供setter
  3. Spring配置檔案中配置依賴關係

2.2.3 修改程式碼

BookServiceImpl.java

public class BookServiceImpl implements BookService {
    //5.刪除業務層中使用new的方式建立的dao物件
    private BookDao xxx;

    public void save() {
        System.out.println("book service save ...");
        xxx.save();
    }
    //6.提供對應的set方法
    public void setBookDao(BookDao xxx) {
        this.xxx = xxx;
    }
}

2.2.4 修改配置

<!-- 
  把Bean裝配進Spring容器
        id 唯一標識,任意起名,但是儘量使用提示的名字
        class  全限定類名(用於反射建立物件)
  小提示:先寫class,只寫類名有提示;再寫id,也有提示
-->
<bean id="bookDao" class="com.cy.dao.impl.BookDaoImpl"/>

<bean id="bookService" class="com.cy.service.impl.BookServiceImpl">
    <bean id="bookService" class="com.cy.service.impl.BookServiceImpl">
        <!--7.配置server與dao的關係-->
        <!--
            property標籤表示配置當前bean的屬性
                name屬性值為對應類中成員變數名。本質上是通過成員變數的setter為其賦值。
                ref屬性值為spring容器中已經存在的另一bean的id
        -->
        <property name="bookDao" ref="bookDao"/>
    </bean>
</bean>

其他程式碼保持不變,直接執行測試方法即可。

3. Spring配置-Bean標籤

3.1 id&class屬性

  • id:唯一標識,同一個Spring容器中不允許重複
  • class:全限定類名,用於反射建立物件

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裝配進Spring容器
        id 唯一標識,任意起名,但是儘量使用提示的名字
        class  全限定類名(用於反射建立物件)
     -->
    <bean class="com.cy.dao.impl.BookDaoImpl" id="bookDao"/>
</beans>

測試程式碼

/**
 * @Description: 測試Spring容器建立和獲取物件
 */
public class UserServiceImpl {

    public static void main(String[] args) {

        // 建立容器物件,並載入配置檔案
        ApplicationContext app = new ClassPathXmlApplicationContext("beans.xml");

        // 從容器物件中獲取bean物件
        BookDao bookDao = (BookDao) app.getBean("bookDao");

        // 使用獲取的bean物件
        bookDao.save();
    }
}

3.2 name 屬性

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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <!--name:為bean指定別名,別名可以有多個,使用逗號,分號,空格進行分隔-->
        <bean id="bookService" name="service service4 bookEbi" class="com.itheima.service.impl.BookServiceImpl">
            <property name="bookDao" ref="bookDao"/>
        </bean>
    
    </beans>
    
    
    
  • 演示程式碼

    package com.cy;
    
    import com.cy.dao.BookDao;
    import com.cy.service.BookService;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class AppForName {
        public static void main(String[] args) {
    
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    
            // 可以通過bean標籤name屬性的值,獲取對應的bean物件
            // BookService bookService = (BookService) ctx.getBean("service");
            
            // 如果傳遞引數不能成功匹配id和name的值,則會報錯。NoSuchBean***
            BookService bookService = (BookService) ctx.getBean("service");
    
            bookService.save();
        }
    }
    
    
    

3.3 scope 屬性

這個很重要,但是一般使用預設值,單例!

  • 概念:單例:在整個專案中,某個類的物件有且僅有一個,這種情況,就是單(個實)例。

  • Spring中的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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <!--scope:為bean設定作用範圍,可選值為單例singloton,非單例prototype-->
        <bean id="bookDao" name="dao" class="com.cy.dao.impl.BookDaoImpl" scope="prototype"/>
    </beans>
    
    
    
  • 演示程式碼

    package com.cy;
    
    import com.cy.dao.BookDao;
    import com.cy.service.BookService;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class AppForScope {
        public static void main(String[] args) {
    
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    
            BookDao bookDao1 = (BookDao) ctx.getBean("bookDao");
            BookDao bookDao2 = (BookDao) ctx.getBean("bookDao");
            System.out.println(bookDao1);
            System.out.println(bookDao2);
    
    
        }
    }
    
    
    
  • Spring可以幫我們維護已有專案中哪些類和物件

    可以單例的

    • Dao
    • Service
    • Servlet/Controller
    • Utils

    不是單例的一般不會讓Spring維護

    • 實體類(資料傳輸的載體)

4. Bean的例項化

4.1 Spring之前物件例項化方式

  • 方式1:通過構造方法直接建立

    // 方式1:通過構造方法直接建立
    BookDaoImpl bookDao = new BookDaoImpl();
    
    
  • 方式2:例項工廠方式

    /* 工廠類 */
    public class BookDaoImplFactory {
        // 提供方法,返回一個BookDaoImpl的物件
        public BookDaoImpl getObject(){
            // 假裝這裡有非常複雜的流程
            return new BookDaoImpl();
        }
    }
    
    
    /** 測試程式碼***/
    // 方式2:例項工廠方式
    // 2.1 建立工廠物件
    BookDaoImplFactory factory = new BookDaoImplFactory();
    // 2.2 通過工廠物件獲取目標物件
    BookDaoImpl booDao1 = factory.getObject();
    
    
  • 方式3:靜態工廠方式

    /* 靜態工廠類 */
    class BookDaoImplFactoryStatic {
        // 提供靜態方法,返回一個BookDaoImpl的物件
        public static BookDaoImpl getObject(){
            // 假裝這裡有非常複雜的流程
            return new BookDaoImpl();
        }
    }
    
    
    // 方式3:靜態工廠方式
    BookDaoImpl bookDao2 = BookDaoImplFactoryStatic.getObject();
    
    

4.2 Spring中構造方法例項化

  • 快速入門案例中,Spring使用的就是通過反射無參構造建立的物件。

  • 無參構造

    OrderDao OrderDao2 = new OrderDaoImpl();
    
    

    對應Spring中的配置

    <!-- 
    	如下配置的效果:
     		通過class的值獲取全限定類名,然後通過反射呼叫無參構造方法,
    		建立物件並裝配進Spring容器,起名為id的值。
    -->
    <bean id="bookDao" class="com.cy.dao.impl.OrderDaoImpl"/>
    
    
  • 如果未提供給無參構造方法,會因為找不到該方法而報錯。NoSuchMethodException *** init()

4.3 Spring中靜態工廠例項化

  • 靜態工廠

    // 方式3:靜態工廠方式
    OrderDao OrderDao2 = OrderDaoFactory.getOrderDao();
    
    

    對應Spring中配置

    <!-- 
    	通過OrderDaoFactory的靜態方法,獲取OrderDao物件
            Spring容器中會產生一個orderDao物件
            該物件的名字是id的值
    --> 
    <bean id="orderDao" class="com.itheima.factory.OrderDaoFactory" factory-method="getOrderDao"/>
    
    

    Spring容器中,獲取方式和之前一樣,通過id獲取物件並使用。

  • 應用場景

    1. 相容老的專案
    2. 建立過程比較複雜的物件,一般都是使用工廠模式

4.4 Spring中例項工廠例項化

  • 例項工廠

    // 方式3:例項工廠方式
    // 建立工廠物件
    UserDaoFactory factory = new UserDaoFactory();
    // 通過工廠物件,得到目標物件
    UserDao userDao = factory.getUserDao();
    
    

    對應Spring中配置

    <!-- 
    	通過UserDaoFactory的成員方法,獲取UserDao物件
            Spring容器中會產生一個UserDaoFacotry物件、UserDao物件
            UserDaoFacotry物件的名字是其id的值
    		UserDao=物件的名字是其id的值
    --> 
    
    <!--方式三:使用例項工廠例項化bean-->
    <!-- 裝配工廠Bean,得到一個工廠的Bean物件 -->
    <bean id="userFactory" class="com.cy.factory.UserDaoFactory"/>
    
    <!-- 通過工廠Bean物件獲取目標Bean物件 -->
    <bean id="userDao" factory-method="getUserDao" factory-bean="userFactory"/>
    
    

    Spring容器中,獲取方式和之前一樣,通過id獲取物件並使用。

4.5 SpringFactoryBean例項化

  • 該方式是在第三種方法的簡化改良。編碼基本雷同,配置相對簡單。

  • 實現步驟

    1. 編寫工廠類實現FactoryBean。類名一般為xxxFactoryBean,泛型為目標物件型別xxx
    2. 實現getObject()方法、getObjectType()方法。
    3. Spring配置檔案中簡單配置。
  • xxxFactoryBean

    package com.cy.factory;
    
    import com.cy.dao.UserDao;
    import com.cy.dao.impl.UserDaoImpl;
    import org.springframework.beans.factory.FactoryBean;
    //FactoryBean建立物件
    public class UserDaoFactoryBean implements FactoryBean<UserDao> {
        //代替原始例項工廠中建立物件的方法
        public UserDao getObject() throws Exception {
            return new UserDaoImpl();
        }
    
        public Class<?> getObjectType() {
            return UserDao.class;
        }
        /**
         *  該方法一般不用重寫 
         *  決定獲取的Bean是否為單例。預設返回true。
         *  true 單例          singleton
         *  false 多例(非單例) prototype
         * @return
         */
        public boolean isSingleton() {
            return true;
        }
    }
    
    
  • XML配置

    <!--
    	方式四:使用FactoryBean例項化bean
    	配置方式和第一種使用構造方法例項化凡是類似,但是class屬性值是一個FactoryBean的實現類
    	Spring容器中會產生一個UserDaoFactoryBean物件、UserDao物件
    		UserDao物件的名字是改標籤的id值
    -->
    <bean id="userDao" class="com.itheima.factory.UserDaoFactoryBean"/>
    
    
  • 應用場景

    Spring在整合其他框架時,多用該方式。

5 生命週期

生命週期:物件從出生到死亡的整個過程。

5.1 配置實現

  1. 提前準備好兩個方法,方法名任意 xxx yyy

    package com.cy.dao.impl;
    
    import com.cy.dao.BookDao;
    
    public class BookDaoImpl implements BookDao {
        public void save() {
            System.out.println("book dao save ...");
        }
        //表示bean初始化對應的操作
        public void xxx(){
            System.out.println("init...");
        }
        //表示bean銷燬前對應的操作
        public void yyy(){
            System.out.println("destory...");
        }
    }
    
    
  2. Spring配置檔案對應bean標籤上新增兩個屬性,屬性值不用帶小括號

    <!--init-method:設定bean初始化生命週期回撥函式-->
    <!--destroy-method:設定bean銷燬生命週期回撥函式,僅適用於單例物件-->
    <bean id="bookDao" class="com.cy.dao.impl.BookDaoImpl" init-method="xxx" destroy-method="yyy"/>
    
    

5.2 實現介面

package com.cy.dao.impl;

import com.cy.dao.BookDao;

public class BookDaoImpl implements BookDao, InitializingBean, DisposableBean {
    public void save() {
        System.out.println("book dao save ...");
    }
    // 實現InitializingBean中抽象方法,該方法會在init-method指定的方法執行後執行
    public void afterPropertiesSet() throws Exception {
        System.out.println("service init");
    }
    
    // 實現DisposableBean充抽象方法
    public void destroy() throws Exception {
        System.out.println("service destroy");
    }
}

5.3 注意

需要手動關閉容器才能看到銷燬程式碼的執行。

  • Spring容器關閉的功能,在Config***的子介面中規定的,需要向下轉型到其子類才能呼叫,一般直接使用ClasspathXMLApplicationContext
  • 也可以註冊關閉的鉤子ctx.registerShutdownHook(),會在執行完程式碼後自動關閉。

5.4 宣告週期(11步)

  • 初始化容器
    • 建立Bean物件(記憶體分配)
    • 執行構造方法
    • 執行屬性注入(set操作)
    • 執行bean初始化方法
  • 使用bean
    • 執行業務操作
  • 關閉/銷燬容器
    • 執行bean銷燬方法

6. 依賴注入

6.1 概念

Dependency Injection,DI

依賴:在A類中用到了B類,就說A依賴B,需要在A類中新增一個B型別的成員變數;

依賴注入:把B類物件設定進A中B型別的成員變數的過程,稱為依賴注入。

Spring會把B類物件注入到A類中B型別的屬性上。自動完成注入。

// 虛擬碼演示
class A{
	// 為B型別的b變數初始化的過程,稱為依賴注入
	B b;
}

依賴注入可以理解成IoC的一種應用場景,反轉的是物件間依賴關係維護注入權

6.2 IoCDI的關係(面試題)

IoC是一種思想(規範),可以把物件的建立權、物件間依賴關係的維護注入權等從程式設計師手中,反轉到了Spring容器中;

DI依賴注入,只是IoC在某個方面的一個具體實現,在 依賴關係維護注入 方面的一個實現。

6.3 注入方式

本質上就是為某個類的成員變數賦值的方式:setter/有參構造

/*
    1. 提供有參構造方法,通過構造方法在建立物件的同時為成員變數賦值
    2. 提供setter,通過setter為成員變數賦值
*/

6.4 Setter方式注入

注入引用型別(容器中已經存在的其他Bean物件)

  1. 保證被注入的Bean和目標Bean都已經裝配到Spring容器

    <bean id="bookDao" class="com.cy.dao.impl.BookDaoImpl"></bean>
    <bean id="userDao" class="com.cy.dao.impl.UserDaoImpl"/>
    <bean id="bookService" class="com.cy.service.impl.BookServiceImpl"></bean>
    
    
  2. BookServiceImpl類中新增UserDao/BookDao的屬性並提供setter

    package com.cy.service.impl;
    
    import com.cy.dao.BookDao;
    import com.cy.dao.UserDao;
    import com.cy.service.BookService;
    
    public class BookServiceImpl implements BookService{
        private BookDao bookDao;
        private UserDao userDao;
        //setter注入需要提供要注入物件的set方法
        public void setUserDao(UserDao userDao) {
            this.userDao = userDao;
        }
        //setter注入需要提供要注入物件的set方法
        public void setBookDao(BookDao bookDao) {
            this.bookDao = bookDao;
        }
    
        public void save() {
            System.out.println("book service save ...");
            bookDao.save();
            userDao.save();
        }
    }
    
    
    
  3. 通過<property>子標籤完成注入

    <bean id="bookDao" class="com.cy.dao.impl.BookDaoImpl"></bean>
    <bean id="userDao" class="com.cy.dao.impl.UserDaoImpl"/>
    <!--注入引用型別-->
    <bean id="bookService" class="com.cy.service.impl.BookServiceImpl">
        <!--property標籤:設定注入屬性-->
        <!--name屬性:設定注入的屬性名,實際是set方法對應的名稱-->
        <!--ref屬性:Spring容器中已經存在的符合要求的Bean-->
        <property name="bookDao" ref="bookDao"/>
        <property name="userDao" ref="userDao"/>
    </bean>
    
    

注入簡單資料型別資料

String + 基本資料型別

只需要把生面的配置檔案中ref屬性換成value屬性即可。

<!--注入簡單型別-->
<bean id="bookDao" class="com.cy.dao.impl.BookDaoImpl">
    <!--property標籤:設定注入屬性-->
    <!--name屬性:設定注入的屬性名,實際是set方法對應的名稱-->
    <!--value屬性:設定注入簡單型別資料值-->
    <property name="connectionNum" value="100"/>
    <property name="databaseName" value="mysql"/>
</bean>

package com.cy.dao.impl;

import com.cy.dao.BookDao;

public class BookDaoImpl implements BookDao {

    private String databaseName;
    private int connectionNum;
    //setter注入需要提供要注入物件的set方法
    public void setConnectionNum(int connectionNum) {
        this.connectionNum = connectionNum;
    }
    //setter注入需要提供要注入物件的set方法
    public void setDatabaseName(String databaseName) {
        this.databaseName = databaseName;
    }

    public void save() {
        System.out.println("book dao save ..."+databaseName+","+connectionNum);
    }
}

6.5 構造器注入

不常用

  • 被裝配的類中提供有參構造,而不需要提供setter

    package com.cy.service.impl;
    
    import com.cy.dao.BookDao;
    import com.cy.dao.UserDao;
    import com.cy.service.BookService;
    
    public class BookServiceImpl implements BookService{
        private BookDao bookDao;
        private UserDao userDao;
    
        // 有參構造,不需要提供setter
        public BookServiceImpl(BookDao bookDao, UserDao userDao) {
            this.bookDao = bookDao;
            this.userDao = userDao;
        }
    
        public void save() {
            System.out.println("book service save ...");
            bookDao.save();
            userDao.save();
        }
    }
    
    
  • XML中通過子標籤配置constructor-arg

    <!-- 標準書寫 -->
    <bean id="bookDao" class="com.cy.dao.impl.BookDaoImpl"></bean>
    <bean id="userDao" class="com.cy.dao.impl.UserDaoImpl"/>
    
    <bean id="bookService" class="com.cy.service.impl.BookServiceImpl">
        <!-- 根據構造方法引數名稱注入
    		name值只為有參構造中形參的名稱
    		ref值為Spring容器中已近存在的其他Bean的id
    		value:簡單型別使用value注入
      -->
        <constructor-arg name="userDao" ref="userDao"/>
        <constructor-arg name="bookDao" ref="bookDao"/>
    </bean>
    
    
  • value屬性注入簡單型別

    <bean id="bookDao" class="com.cy.dao.impl.BookDaoImpl">
        <!-- 根據構造方法引數型別注入 -->
        <constructor-arg type="int" value="10"/>
        <constructor-arg type="java.lang.String" value="mysql"/>
    </bean>
    
    

6.6 自動裝配

自動為當前Bean完成依賴注入,簡稱自動裝配,可取值byName | byType | constructor,分別代表按照

  1. byType:按照屬性型別Spring容器中bean進行匹配,完成自動裝配注入
  2. byName:按照屬性名Spring容器中bean的id進行匹配,完成自動裝配注入
  3. constructor:按照構造方法的形參型別Spring容器中bean進行匹配,完成自動裝配注入

注意:上述中屬性值的是setter或者是構造形參,而非成員變數本身。

xml中配置:把所有的Bean都配置進Spring容器。

<bean id = "bookDao" class="com.cy.dao.impl.BookDaoImpl"/>
<!-- <bean class="com.cy.dao.impl.BookDaoImpl"/> -->
<!-- autowire屬性:開啟自動裝配,通常使用按型別裝配-->
<bean id="bookService" class="com.cy.service.impl.BookServiceImpl" autowire="byType"/>


java程式碼

package com.cy.service.impl;

import com.cy.dao.BookDao;
import com.cy.service.BookService;

public class BookServiceImpl implements BookService{
    private BookDao bookDao;

    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }

    public void save() {
        System.out.println("book service save ...");
        bookDao.save();
    }
}

6.7 注意事項

  1. 優選自動裝配
  2. 使用按型別裝配時(byType)必須保障容器中相同型別的bean唯一,推薦使用
  3. 使用按名稱裝配時(byName)必須保障容器中具有指定名稱的bean,因變數名與配置耦合,不推薦使用
  4. 自動裝配優先順序低於setter注入與構造器注入,同時出現時自動裝配配置失效

6.8 集合注入

瞭解即可。

<bean id="bookDao" class="com.cy.dao.impl.BookDaoImpl">

    <!--
        單例集合  list  set  array
            配置通用  ,建議使用list
        雙列集合  map properties
            配置通用 ,建議使用Map
    -->
 
    <!--set集合注入-->
    <property name="set">
        <array>
            <value>100</value>
            <value>200</value>
            <value>300</value>
        </array>
    </property>
    <!--map集合注入-->
    <property name="map">
        <props>
            <prop key="country">china</prop>
            <prop key="province">henan</prop>
            <prop key="city">kaifeng</prop>
        </props>
    </property>
    <!--Properties注入-->
    <property name="properties">

        <map>
            <entry key="country" value="china"/>
            <entry key="province" value="henan"/>
            <entry key="city" value="kaifeng"/>
        </map>
    </property>
</bean>

package com.cy.dao.impl;

import com.cy.dao.BookDao;

import java.util.*;

public class BookDaoImpl implements BookDao {

    private String[] array;

    private List<String> list;

    private Set<String> set;

    private Map<String,String> map;

    private Properties properties;

    public void setArray(String[] array) {
        this.array = array;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    public void setSet(Set<String> set) {
        this.set = set;
    }

    public void setMap(Map<String, String> map) {
        this.map = map;
    }

    public void setProperties(Properties properties) {
        this.properties = properties;
    }

    public void save() {
        System.out.println("book dao save ...");

        System.out.println("遍歷陣列:" + Arrays.toString(array));

        System.out.println("遍歷List" + list);

        System.out.println("遍歷Set" + set);

        System.out.println("遍歷Map" + map);

        System.out.println("遍歷Properties" + properties);
    }
}

7. 案例練習

無論是自己寫的類要裝配進Spring容器,還是第三方的類要裝配進Spring容器,只需要遵循Spring的配置規則即可。

後者與前者的不同,僅僅是把自己編寫程式碼變成了匯入依賴座標,配置方式一致。

7.1 DruidDataSource

7.1.1 匯入依賴座標

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.cy</groupId>
    <artifactId>ssm01_spring01_11_datasource</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
  		<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.16</version>
        </dependency>
        
    </dependencies>
</project>

7.1.2 Spring裝配配置

<bean class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/spring_db"/>
    <property name="username" value="root"/>
    <property name="password" value="root"/>
</bean>

7.1.3 測試

package com.itheima;

import com.itheima.dao.BookDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import javax.sql.DataSource;

public class App {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        DataSource dataSource = (DataSource) ctx.getBean("dataSource");
        System.out.println(dataSource);
    }
}

7.2 C3P0資料來源

老牌資料來源管理工具,曾經久不衰。

7.2.1 匯入依賴座標

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.itheima</groupId>
    <artifactId>ssm01_spring01_11_datasource</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
    </dependencies>
</project>

7.2.2 Spring裝配配置

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="com.mysql.jdbc.Driver"/>
    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring_db"/>
    <property name="user" value="root"/>
    <property name="password" value="root"/>
    <property name="maxPoolSize" value="1000"/>
</bean>

7.2.3 測試

package com.cy;

import com.cy.dao.BookDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import javax.sql.DataSource;

public class App {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        DataSource dataSource = (DataSource) ctx.getBean("dataSource");
        System.out.println(dataSource);
    }
}

8 引入properties檔案

8.1 建立properties檔案

  • jdbc.properties

    # 不要使用username,否則會錯誤的獲取到當前系統的使用者名稱。建議使用jdbc.username
    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://127.0.0.1:3306/spring_db
    jdbc.username=root
    jdbc.password=root
    
    

8.2 beans.xml檔案引入 jdbc.properties檔案

<!-- 在類路徑下載入指定名稱的properties配置檔案,classpath:可以省略不寫。下同  -->
<context:property-placeholder location="classpath:jdbc.properties"/>

<!-- 在類路徑下載入多個指定名稱的properties配置檔案 -->
<context:property-placeholder location="classpath:jdbc.properties,jdbc2.properties"/>

<!-- 在類路徑下載入所有的properties配置檔案 -->
<context:property-placeholder location="classpath:*.properties"/>
<!-- 
	在類路徑+jar包中(整個專案下)載入所有的properties配置檔案
    統配會造成效率降低,速度變慢
 -->
<context:property-placeholder location="classpath*:*.properties"/>

<!--
	使用屬性佔位符${},可以通過properties檔案中的key讀取到對應的值
		OGNL 
    	${} 所有的框架都支援這個種寫法,從當前容器物件中根據key獲取值

    Spring容器會把當前系統的內建變數整合進自己的容器 username=當前系統的使用者名稱
	且優先順序高於我們自己配置的。
    ${username} 會獲取當前系統的使用者名稱

	解決方案:
		1. 不要使用username,使用諸如jdbc.username。推薦寫法。
		2. 通過其屬性system-properties-mode="NEVER"配置不載入系統屬性。但是不推薦。
 -->

    <bean class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <bean id="bookDao" class="com.cy.dao.impl.BookDaoImpl">
        <property name="name" value="${username}"/>
    </bean>


8.3 程式碼測試

package com.cy;

import com.cy.dao.BookDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import javax.sql.DataSource;

public class App {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
        bookDao.save();
    }
}