前言
Spring技術(shù)是JavaEE開發(fā)必備技能,企業(yè)開發(fā)技術(shù)選型命中率>90%。
Spring具有簡(jiǎn)化開發(fā),降低企業(yè)級(jí)開發(fā)的復(fù)雜性和框架整合,高效整合其他技術(shù),提高企業(yè)級(jí)應(yīng)用開發(fā)與運(yùn)行效率的特點(diǎn)。
本文詳細(xì)講解Spring快速入門。
簡(jiǎn)介
官網(wǎng):spring.io
Spring發(fā)展到今天已經(jīng)形成了一種開發(fā)的生態(tài)圈,Spring提供了若干個(gè)項(xiàng)目,每個(gè)項(xiàng)目用于完成特定的功能。以下就是Spring的全家桶。
本文主要講解Spring Framework
Spring Framework
是Spring生態(tài)圈中最基礎(chǔ)的項(xiàng)目,是其他項(xiàng)目的根基。
快速入門
1. ApplicationContext配置文件
本文需要?jiǎng)?chuàng)建applicationContext.xml
文件放入resources
中內(nèi)容如下:
<?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 -->
</beans>
下文所提到的bean
的配置均是在此文件中進(jìn)行配置。
2. IoC(Inversion of Control)控制反轉(zhuǎn)
2.1 概念
使用對(duì)象時(shí),由主動(dòng)new
產(chǎn)生對(duì)象轉(zhuǎn)換為由外部提供對(duì)象,此過程中對(duì)象創(chuàng)建控制權(quán)由程序轉(zhuǎn)移到外部,此思想稱為控制反轉(zhuǎn)。
Spring技術(shù)對(duì)IoC
思想進(jìn)行了實(shí)現(xiàn)。
Spring提供了一個(gè)容器,稱為IoC容器
,用來充當(dāng)IoC
思想中的外部。
IoC容器
負(fù)責(zé)對(duì)象的創(chuàng)建,初始化等一系列工作,被創(chuàng)建或被管理的對(duì)象在IoC
容器中統(tǒng)稱為Bean
。
2.2 IoC快速入門
2.2.1 在pom.xml中導(dǎo)入Spring坐標(biāo)
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.19</version>
</dependency>
2.2.2 定義Spring管理的類(接口)
public interface BookService {
void save();
}
public class BookServiceImpl implements BookService {
private BookDao bookDao = new BookDaoImpl();
@Override
public void save() {
bookDao.save();
}
}
2.2.3 創(chuàng)建Spring的xml配置文件,配置對(duì)應(yīng)類作為Spring管理的bean
<?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="bookService" class="com.hao.service.impl.BookServiceImpl"/>
</beans>
注意事項(xiàng):bean
定義時(shí)id
屬性在同一個(gè)上下文中不能重復(fù)
2.2.4 初始化IoC容器,通過容器獲取bean
public class App {
public static void main(String[] args) {
/* 加載配置文件 獲取IoC容器 */
ApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");
/* 獲取bean */
BookService bookService = (BookService) cxt.getBean("bookService");
bookService.save();
}
}
現(xiàn)在運(yùn)行App
類可以看到這里可以正常得到bookService
并使用。
3. DI(Dependency injection)依賴注入
3.1 概念
在容器中建立bean與bean之間的依賴關(guān)系的整個(gè)過程,稱為依賴注入。
3.2 快速入門
3.2.1 刪除使用new的形式創(chuàng)建對(duì)象的代碼
public class BookServiceImpl implements BookService {
/* 刪除業(yè)務(wù)層中使用new的方式創(chuàng)建的dao對(duì)象 */
private BookDao bookDao;
@Override
public void save() {
System.out.println("book service save...");
bookDao.save();
}
}
3.2.2 提供依賴對(duì)象對(duì)應(yīng)的setter方法
public class BookServiceImpl implements BookService {
/* 刪除業(yè)務(wù)層中使用new的方式創(chuàng)建的dao對(duì)象 */
private BookDao bookDao;
@Override
public void save() {
System.out.println("book service save...");
bookDao.save();
}
/* 提供對(duì)應(yīng)的setter方法 */
public void setBookDao(BookDao bookDao) {
System.out.println("set book dao...");
this.bookDao = bookDao;
}
}
3.2.3 配置Service與Dao之間的關(guān)系
<bean id="bookDao" class="com.hao.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="com.hao.service.impl.BookServiceImpl">
<!-- 配置Service與Dao的關(guān)系 -->
<!--
property標(biāo)簽:表示配置當(dāng)前bean的屬性
name屬性:表示配置哪一個(gè)具體的屬性
ref屬性:表示參照哪一個(gè)bean 可以是id,也可以是name 建議使用id
-->
<property name="bookDao" ref="bookDao"/>
</bean>
4. bean配置
4.1 bean基礎(chǔ)配置
4.2 bean別名配置
注意:獲取bean無論是通過id
還是name
獲取,如果無法獲取到,將拋出異常NoSuchBeanDefinitionException
,意思是這個(gè)bean
沒有被定義。此問題很大可能是配置時(shí)寫錯(cuò),或者是獲取時(shí)候?qū)戝e(cuò)導(dǎo)致的,到時(shí)候看看修改一下就解決了。
4.3 bean作用范圍
由此可知bean
默認(rèn)是創(chuàng)建的單例對(duì)象。
4.3.1 適合交給容器進(jìn)行管理的bean
表現(xiàn)層對(duì)象
業(yè)務(wù)層對(duì)象
數(shù)據(jù)層對(duì)象
工具對(duì)象
4.3.2 不適合交給容器進(jìn)行管理的bean
封裝實(shí)體的域?qū)ο?/p>
5. bean實(shí)例化
bean
本質(zhì)上就是對(duì)象,創(chuàng)建bean
使用構(gòu)造方法完成。
實(shí)例化bean
有四種方式。
5.1 構(gòu)造方法(常用)
5.1.1 提供可訪問的構(gòu)造方法
public class BookDaoImpl implements BookDao {
private BookDaoImpl() {
System.out.println("book dao constructor is running...");
}
@Override
public void save() {
System.out.println("book dao save...");
}
}
5.1.2 配置
<bean id="bookDao" class="com.hao.dao.impl.BookDaoImpl"/>
這里注意一個(gè)小細(xì)節(jié),就算無參構(gòu)造方法是私有的,也是可以通過無參構(gòu)造方法來創(chuàng)建對(duì)象。但是如果無參構(gòu)造方法不存在,將拋出異常BeanCreationException
5.2 靜態(tài)工廠(了解)
5.2.1 提供靜態(tài)工廠類
public class OrderDaoFactory {
public static OrderDao getOrderDao() {
return new OrderDaoImpl();
}
}
5.2.2 配置
<bean id="orderDao" class="com.hao.factory.OrderDaoFactory" factory-method="getOrderDao"/>
5.3 實(shí)例工廠(了解)
5.3.1 提供實(shí)例工廠類
public class UserDaoFactory {
public UserDao getUserDao() {
return new UserDaoImpl();
}
}
5.3.2 配置
<bean id="userFactory" class="com.hao.factory.UserDaoFactory"/>
<bean id="userDao" factory-bean="userFactory" factory-method="getUserDao"/>
5.4 使用FactoryBean(了解)
5.4.1 提供FactoryBean實(shí)現(xiàn)類
public class UserDaoFactoryBean implements FactoryBean<UserDao> {
/* 代替原始實(shí)例工廠中創(chuàng)建對(duì)象的方法 */
@Override
public UserDao getObject() throws Exception {
return new UserDaoImpl();
}
/* 對(duì)象類型 */
@Override
public Class<?> getObjectType() {
return UserDao.class;
}
/* 創(chuàng)建的對(duì)象是否是單例 默認(rèn)是單例 */
@Override
public boolean isSingleton() {
return true;
}
}
5.4.2 配置
<bean id="userDao" class="com.hao.factory.UserDaoFactoryBean"/>
6. bean生命周期
6.1 概念
生命周期:從創(chuàng)建到消亡的完整過程
bean
生命周期:bean
從創(chuàng)建到消亡的整體過程
bean
生命周期控制:在bean
創(chuàng)建后到銷毀前做一些事情
6.2 bean生命周期控制
有兩種方式可以來實(shí)現(xiàn)bean
生命周期的控制。
6.2.1 提供生命周期控制方法
public class BookDaoImpl implements BookDao {
@Override
public void save() {
System.out.println("book dao save...");
}
/* 定義該方法 表示bean初始化對(duì)應(yīng)的操作 */
public void init() {
System.out.println("book dao init...");
}
/* 定義該方法 表示bean銷毀前對(duì)應(yīng)的操作 */
public void destory() {
System.out.println("book dao destory...");
}
}
配置如下
<bean id="bookDao" class="com.hao.dao.impl.BookDaoImpl" init-method="init" destroy-method="destory"/>
6.2.2 實(shí)現(xiàn)InitializingBean, DisposableBean接口
public class BookServiceImpl implements BookService , InitializingBean, DisposableBean {
@Override
public void save() {
System.out.println("book service save...");
}
@Override
public void destroy() throws Exception {
System.out.println("book service destroy...");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("book service init...");
}
}
6.3 bean銷毀時(shí)機(jī)
容器關(guān)閉前觸發(fā)bean
的銷毀
關(guān)閉容器方式有兩種:手工關(guān)閉容器和注冊(cè)關(guān)閉鉤子。
6.3.1 手工關(guān)閉容器
ConfigurableApplicationContext
接口close()
操作
public class AppForLifeCycle {
public static void main(String[] args) {
ClassPathXmlApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");
/* 獲取bean */
BookDao bookDao = (BookDao) cxt.getBean("bookDao");
bookDao.save();
/* 關(guān)閉容器 close比較暴力 */
cxt.close();
}
}
6.3.2 注冊(cè)關(guān)閉鉤子,在虛擬機(jī)退出前先關(guān)閉容器再退出虛擬機(jī)
ConfigurableApplicationContext
接口registerShutdownHook()
操作
public class AppForLifeCycle {
public static void main(String[] args) {
ClassPathXmlApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");
/* 注冊(cè)關(guān)閉鉤 在程序退出之前會(huì)先關(guān)閉容器 */
cxt.registerShutdownHook();
/* 獲取bean */
BookDao bookDao = (BookDao) cxt.getBean("bookDao");
bookDao.save();
}
}
7. 依賴注入方式
依賴注入的方式分為setter
注入和構(gòu)造器注入。
- setter注入包含:簡(jiǎn)單類型和引用類型
- 構(gòu)造器注入包含:簡(jiǎn)單類型和引用類型
7.1 setter注入--引用類型
7.1.1 在bean中定義引用類型屬性并提供可訪問的set方法
public class BookServiceImpl implements BookService {
private BookDao bookDao;
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
}
7.1.2 配置中使用property標(biāo)簽ref屬性注入引用類型對(duì)象
<bean id="bookService" class="com.hao.service.impl.BookServiceImpl">
<property name="bookDao" ref="bookDao"/>
</bean>
7.2 setter注入--簡(jiǎn)單類型
7.2.1 在bean中定義簡(jiǎn)單類型屬性并提供可訪問的set方法
public class BookDaoImpl implements BookDao {
private int connectionNum;
private String databaseName;
public void setConnectionNum(int connectionNum) {
this.connectionNum = connectionNum;
}
public void setDatabaseName(String databaseName) {
this.databaseName = databaseName;
}
}
7.2.2 配置中使用property標(biāo)簽value屬性注入簡(jiǎn)單類型數(shù)據(jù)
<bean id="bookDao" class="com.hao.dao.impl.BookDaoImpl">
<property name="connectionNum" value="123"/>
<property name="databaseName" value="mysql"/>
</bean>
7.3 構(gòu)造器注入--引用類型 (了解)
7.3.1 在bean中定義引用類型屬性并提供可訪問的構(gòu)造方法
public class BookServiceImpl implements BookService {
private BookDao bookDao;
public BookServiceImpl(BookDao bookDao) {
this.bookDao = bookDao;
}
}
7.3.2 配置中使用constructor-arg標(biāo)簽ref屬性注入引用類型對(duì)象
<bean id="bookService" class="com.hao.service.impl.BookServiceImpl">
<constructor-arg name="bookDao" ref="bookDao"/>
</bean>
7.4 構(gòu)造器注入--簡(jiǎn)單類型(了解)
7.4.1 在bean中定義簡(jiǎn)單類型屬性并提供可訪問的構(gòu)造方法
public class BookDaoImpl implements BookDao {
private int connectionNum;
private String databaseName;
public BookDaoImpl(int connectionNum, String databaseName) {
this.connectionNum = connectionNum;
this.databaseName = databaseName;
}
}
7.4.2 配置中使用constructor-arg標(biāo)簽value屬性注入簡(jiǎn)單類型數(shù)據(jù)
<bean id="bookDao" class="com.hao.dao.impl.BookDaoImpl">
<constructor-arg name="connectionNum" value="10"/>
<constructor-arg name="databaseName" value="mysql"/>
</bean>
該方式耦合度比較高。
7.4.3 配置中使用constructor-arg標(biāo)簽type屬性設(shè)置按形參類型注入數(shù)據(jù)
<bean id="bookDao" class="com.hao.dao.impl.BookDaoImpl">
<constructor-arg type="int" value="10"/>
<constructor-arg type="java.lang.String" value="mysql"/>
</bean>
該方式解決參數(shù)名耦合問題。
7.4.4 配置中使用constructor-arg標(biāo)簽value屬性設(shè)置按形參位置注入數(shù)據(jù)
<bean id="bookDao" class="com.hao.dao.impl.BookDaoImpl">
<constructor-arg index="0" value="666"/>
<constructor-arg index="1" value="mysql"/>
</bean>
該方式解決參數(shù)類型重復(fù)問題。
7.5 依賴注入方式選擇
a. 強(qiáng)制依賴使用構(gòu)造器進(jìn)行,使用setter
注入有概率不進(jìn)行注入導(dǎo)致null
對(duì)象出現(xiàn)
b. 可選依賴使用setter
注入進(jìn)行,靈活性強(qiáng)
c. Spring框架倡導(dǎo)使用構(gòu)造器,第三方框架內(nèi)部大多數(shù)采用構(gòu)造器注入的形式進(jìn)行數(shù)據(jù)初始化,相對(duì)嚴(yán)謹(jǐn)
d. 如果有必要可以兩者同時(shí)使用呢,使用構(gòu)造器注入完成強(qiáng)制依賴的注入,使用setter
注入完成可選依賴的注入
e. 實(shí)際開發(fā)過程中還要根據(jù)實(shí)際情況分析,如果受控對(duì)象沒有提供setter
方法就必須使用構(gòu)造器注入
f. 自己開發(fā)的模塊推薦使用setter
注入
8. 依賴自動(dòng)裝配(autowire)
8.1 概念
IoC容器
根據(jù)bean
所依賴的資源在容器中自動(dòng)查找并注入到bean
中的過程成為自動(dòng)裝配。
8.2 自動(dòng)裝配方式
public class BookServiceImpl implements BookService{
private BookDao bookDao;
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
}
8.2.1 按類型(常用)
<bean id="bookDao" class="com.hao.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="com.hao.service.impl.BookServiceImpl" autowire="byType"/>
8.2.2 按名稱
<bean id="bookDao" class="com.hao.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="com.hao.service.impl.BookServiceImpl" autowire="byName"/>
注意:屬性名稱bookDao
必須與屬性bean
的id
或name
一致
8.3 特征
a. 自動(dòng)裝配用于引用類型依賴注入,不能對(duì)簡(jiǎn)單類型進(jìn)行操作。
b. 使用按類型裝配時(shí)(byType
)必須保障容器中相同類型的bean
唯一,推薦使用。
c. 使用按名稱裝配時(shí)(byName
)必須保障容器中具有指定名稱的bean
,因變量名與配置耦合,不推薦使用。
d. 自動(dòng)裝配優(yōu)先級(jí)低于setter
注入與構(gòu)造器注入,同時(shí)出現(xiàn)時(shí)自動(dòng)裝配配置無效。
9. 集合注入
public class BookDaoImpl implements BookDao {
private int[] array;
private List<String> list;
private Set<String> set;
private Map<String, String> map;
private Properties properties;
public void setArray(int[] 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;
}
}
9.1 注入數(shù)組對(duì)象
<bean id="bookDao" class="com.hao.dao.impl.BookDaoImpl">
<property name="array">
<array>
<value>100</value>
<value>200</value>
<value>300</value>
</array>
</property>
</bean>
9.2 注入List對(duì)象(重點(diǎn))
<bean id="bookDao" class="com.hao.dao.impl.BookDaoImpl">
<property name="list">
<list>
<value>ithao</value>
<value>hao</value>
<value>java</value>
</list>
</property>
</bean>
9.3 注入Set對(duì)象
<bean id="bookDao" class="com.hao.dao.impl.BookDaoImpl">
<property name="set">
<set>
<value>ithao</value>
<value>hao</value>
<value>spring</value>
</set>
</property>
</bean>
9.4 注入Map對(duì)象(重點(diǎn))
<bean id="bookDao" class="com.hao.dao.impl.BookDaoImpl">
<property name="map">
<map>
<entry key="country" value="China"/>
<entry key="province" value="henan"/>
<entry key="city" value="yuzhou"/>
</map>
</property>
</bean>
9.5 注入Properties對(duì)象
<bean id="bookDao" class="com.hao.dao.impl.BookDaoImpl">
<property name="properties">
<props>
<prop key="country">China</prop>
<prop key="province">henan</prop>
<prop key="city">yuzhou</prop>
</props>
</property>
</bean>
10. 第三方資源配置管理
這里以第三方資源druid
為例來講解詳細(xì)步驟。
10.1 在pom.xml中導(dǎo)入druid坐標(biāo)
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.9</version>
</dependency>
10.2 配置數(shù)據(jù)源對(duì)象作為Spring管理的bean
這個(gè)bean
其實(shí)就是管理DruidDataSource
對(duì)象
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Diver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
測(cè)試一下如下:
public class App {
public static void main(String[] args) {
ApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");
DataSource dataSource = (DataSource) cxt.getBean("dataSource");
System.out.println(dataSource);
}
}
11. 加載properties文件
11.1 在配置文件中開啟context命名空間
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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">
11.2 使用context命名空間,加載指定properties文件
比如創(chuàng)建一個(gè)jdbc.properties
文件,加載jdbc.properties
有多種寫法如下:
11.2.1 正常加載properties
<context:property-placeholder location="jdbc.properties"/>
11.2.2 不加載系統(tǒng)屬性
<context:property-placeholder location="jdbc.properties" system-properties-mode="NEVER"/>
11.2.3 加載多個(gè)properties文件
<context:property-placeholder location="jdbc.properties, jdbc2.properties"/>
11.2.4 加載所有properties文件
<context:property-placeholder location="*.properties"/>
11.2.5 加載properties文件標(biāo)準(zhǔn)格式
<context:property-placeholder location="classpath:*.properties"/>
11.2.6 從類路徑或jar包中搜索并加載properties文件
<context:property-placeholder location="classpath*:*.properties"/>
11.3 使用${}讀取加載的屬性值
在jdbc.properties
文件中存入druid
的配置信息如下:
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=123456
那么關(guān)于druid
的bean
配置就可以寫成如下:
<bean id="dataSource" 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>
總結(jié)
以上就是關(guān)于Spring快速入門詳解的全部內(nèi)容,本文詳細(xì)介紹了使用xml
配置的方式來使用Spring Framework
。
如果有什么問題,我們可以一起交流討論解決。
最后,希望可以幫助到有需要的碼友。