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的提供的解決方案
-
Mybatis
:Dao
層框架 -
SpringMVC
:web
層框架 -
Spring
:軟體三層中都可以看到Spring
的應用場景
-
1.4 發展歷程
- Spring之父
Rod Johnson
- EJB
Enterprise Java Bean
,sun
公司提出來的大型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演化過程
基於介面程式設計:
service
和dao
之間高度耦合工廠+配置檔案:解除了耦合,留下配置檔案和dao/工廠耦合,這種耦合是我們期望的一種耦合方式
-
IoC
控制反轉 -
Inverse of Control
把物件的建立權、依賴的注入權從程式設計師手中,反轉到了
Spring
容器建立並提供
2. Spring quick Start
2.0 準備工作:配置私服
<!-- 略 -->
2.1 IOC實現步驟
- 匯入
Spring
依賴座標:spring-context-5.2.10.RELEASE
- 編寫
service/dao
介面和實現類 -
Spring
核心配置檔案中配置service/dao
實現類 - 測試類中建立
Spring
容器物件,並通過物件獲取service/dao
實現類物件 - 呼叫
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 Injection
。Service
用到dao
,Service
就依賴了Dao
,就需要把Dao
注入到Service
中。
之前的注入方式:
- 之前
Service
中的dao
都是我們自己new
的;
使用Spring
中的依賴注入
- 我們就不需要自己
new
,Spring
會自動找到(建立)Dao
物件,並設定給Service
中的成員變數。
2.2.2 實現步驟
- 基於
IoC
快速入門程式碼,完成下面操作。 - 刪除被依賴物件的new建立程式碼,並提供
setter
-
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
獲取物件並使用。 -
應用場景
- 相容老的專案
- 建立過程比較複雜的物件,一般都是使用工廠模式
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 Spring
中FactoryBean
例項化
-
該方式是在第三種方法的簡化改良。編碼基本雷同,配置相對簡單。
-
實現步驟
- 編寫工廠類實現
FactoryBean
。類名一般為xxxFactoryBean
,泛型為目標物件型別xxx
- 實現
getObject()
方法、getObjectType()
方法。 -
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 配置實現
-
提前準備好兩個方法,方法名任意 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..."); } }
-
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 IoC
和DI
的關係(面試題)
IoC
是一種思想(規範),可以把物件的建立權、物件間依賴關係的維護注入權等從程式設計師手中,反轉到了Spring
容器中;
DI
依賴注入,只是IoC
在某個方面的一個具體實現,在 依賴關係維護注入 方面的一個實現。
6.3 注入方式
本質上就是為某個類的成員變數賦值的方式:setter/有參構造
/*
1. 提供有參構造方法,通過構造方法在建立物件的同時為成員變數賦值
2. 提供setter,通過setter為成員變數賦值
*/
6.4 Setter方式注入
注入引用型別(容器中已經存在的其他Bean物件)
-
保證被注入的
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>
-
在
BookServiceImpl
類中新增UserDao/BookDao
的屬性並提供setterpackage 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(); } }
-
通過
<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
,分別代表按照
-
byType
:按照屬性型別和Spring容器中bean進行匹配,完成自動裝配注入 -
byName
:按照屬性名和Spring容器中bean的id進行匹配,完成自動裝配注入 -
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 注意事項
- 優選自動裝配
- 使用按型別裝配時(byType)必須保障容器中相同型別的bean唯一,推薦使用
- 使用按名稱裝配時(byName)必須保障容器中具有指定名稱的bean,因變數名與配置耦合,不推薦使用
- 自動裝配優先順序低於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();
}
}