系列文章目錄
IDEA創(chuàng)建項(xiàng)目的操作步驟以及在虛擬機(jī)里面創(chuàng)建Scala的項(xiàng)目簡(jiǎn)單介紹
IDEA項(xiàng)目實(shí)踐——?jiǎng)?chuàng)建Java項(xiàng)目以及創(chuàng)建Maven項(xiàng)目案例、使用數(shù)據(jù)庫(kù)連接池創(chuàng)建項(xiàng)目簡(jiǎn)介
IDEWA項(xiàng)目實(shí)踐——mybatis的一些基本原理以及案例
IDEA項(xiàng)目實(shí)踐——?jiǎng)討B(tài)SQL、關(guān)系映射、注解開發(fā)
文章目錄
第1章 Spring 概述
1.1 Spring 框架是什么
1.2 Spring 優(yōu)點(diǎn)
1.3 Spring 體系結(jié)構(gòu)
第2章 IoC 控制反轉(zhuǎn)
2.1 開發(fā)工具準(zhǔn)備
2.2 Spring 的第一個(gè)程序
2.2.1 創(chuàng)建 maven 項(xiàng)目
2.2.2 引入 maven 依賴 pom.xml
2.2.3 定義接口與實(shí)體類
2.2.4 創(chuàng)建 Spring 配置文件
2.2.5 定義測(cè)試類
2.2.6 使用 spring 創(chuàng)建非自定義類對(duì)象
2.2.7 容器接口和實(shí)現(xiàn)類
2.3 基于 XML 的 DI
2.3.1 注入分類
(1) set 注入(掌握)
A、 簡(jiǎn)單類型
B、引用類型
(2) 構(gòu)造注入(理解)
2.3.2 引用類型屬性自動(dòng)注入
(1) byName 方式自動(dòng)注入
(2) byType 方式自動(dòng)注入
2.3.3 為應(yīng)用指定多個(gè) Spring 配置文件
2.4 基于注解的 DI
2.4.1 定義 Bean 的注解@Component(掌握)
2.4.2 簡(jiǎn)單類型屬性注入@Value(掌握)
2.4.3 byType 自動(dòng)注入@Autowired(掌握)
2.4.4 byName 自動(dòng)注入@Autowired 與@Qualifier(掌握)
2.4.5 JDK 注解@Resource 自動(dòng)注入(掌握)
2.4.6 注解與 XML 的對(duì)比
第3章?傳統(tǒng)案例實(shí)現(xiàn)與spring對(duì)比
3.1? 項(xiàng)目目錄
3.2?person類
3.3?在pom.xml文件導(dǎo)入下面的依賴
3.4?寫一個(gè)配置文件?
3.5? 利用spring優(yōu)化的地方
總結(jié)
前言
本文主要是對(duì)spring框架的簡(jiǎn)單介紹以及LOC控制反轉(zhuǎn)介紹,以及基于xml的DI和注解開發(fā)案例講解,文章當(dāng)中的案例經(jīng)供參考。具體的開發(fā)應(yīng)用要按照具體的開發(fā)來(lái)書寫。
第1章 Spring 概述
1.1 Spring 框架是什么
Spring 是于 2003 年興起的一個(gè)輕量級(jí)的 Java 開發(fā)框架,它是為了解決企業(yè)應(yīng)用開發(fā)的復(fù)雜性而創(chuàng)建的。Spring 的核心是控制反轉(zhuǎn)(IoC)和面向切面編程(AOP)。Spring 是可以在 Java SE/EE 中使用的輕量級(jí)開源框架。
Spring 的主要作用就是為代碼“解耦”,降低代碼間的耦合度。就是讓對(duì)象和對(duì)象(模塊和模塊)之間關(guān)系不是使用代碼關(guān)聯(lián),而是通過(guò)配置來(lái)說(shuō)明。 即在 Spring 中說(shuō)明對(duì)象(模塊)的關(guān)系。
程序開發(fā)的原則:高內(nèi)聚、低耦合【類與類之間的關(guān)系不能太精密】
Spring 根據(jù)代碼的功能特點(diǎn),使用 Ioc 降低業(yè)務(wù)對(duì)象之間耦合度。IoC 使 得主業(yè)務(wù)在相互調(diào)用過(guò)程中,不用再自己維護(hù)關(guān)系了,即不用再自己創(chuàng)建要使用的對(duì)象了。而是由 Spring 容器統(tǒng)一管理,自動(dòng)“注入”,注入即賦值。 而 AOP 使得系統(tǒng)級(jí)服務(wù)得到了最大復(fù)用,且不用再由程序員手工將系統(tǒng)級(jí)服務(wù) “混雜”到主業(yè)務(wù)邏輯中了,而是由 Spring 容器統(tǒng)一完成“織入”。
官網(wǎng):Spring | Home
Spring是面向切面的編程
1.2 Spring 優(yōu)點(diǎn)
Spring 是一個(gè)框架,是一個(gè)半成品的軟件。有 20 個(gè)模塊組成。它是一個(gè) 容器管理對(duì)象,容器是裝東西的,Spring 容器不裝文本,數(shù)字。裝的是對(duì)象。 Spring 是存儲(chǔ)對(duì)象的容器。
(1) 輕量
Spring 框架使用的 jar 都比較小,一般在 1M 以下或者幾百 kb。Spring 核心功能的所需的 jar 總共在 3M 左右。
Spring 框架運(yùn)行占用的資源少,運(yùn)行效率高。不依賴其他 jar
(2) 針對(duì)接口編程,解耦合
Spring 提供了 Ioc 控制反轉(zhuǎn),由容器管理對(duì)象,對(duì)象的依賴關(guān)系。原來(lái)在程序代碼中的對(duì)象創(chuàng)建方式,現(xiàn)在由容器完成。對(duì)象之間的依賴,解耦合。
IOC是( Inversion of Control )的縮寫,多數(shù)書籍翻譯成“控制反轉(zhuǎn)”,還有些書籍翻譯成為“控制反向”或者“控制倒置”。
程序的流程控制權(quán)相對(duì)于傳統(tǒng)的面向過(guò)程編程而言發(fā)生了反轉(zhuǎn)。
下面是維基百科的描述
In software engineering, inversion of control (IoC) is a programming principle. IoC inverts the flow of control as compared to traditional control flow.
看到這里大家可能會(huì)覺得云里霧里的…控制反轉(zhuǎn)(Inversion of Control)實(shí)際是控制(Control)和反轉(zhuǎn)(Inversion)兩個(gè)詞的組合,所以撥開云霧的關(guān)鍵在于理解控制和反轉(zhuǎn)。
“反轉(zhuǎn)”
- 程序的流程控制權(quán)發(fā)生了轉(zhuǎn)變
- 應(yīng)用程序與第三方代碼之間的調(diào)用關(guān)系發(fā)生了轉(zhuǎn)變
復(fù)用代碼有三種方式:類庫(kù)、框架、設(shè)計(jì)模式。
- 類庫(kù):強(qiáng)調(diào)代碼復(fù)用;
- 定義一組可復(fù)用的代碼,供其他程序調(diào)用——拿來(lái)主義,別人的東西拿來(lái)用,用別人的錘子砸核桃。
- 框架:強(qiáng)調(diào)設(shè)計(jì)復(fù)用;
- 定義程序的體系結(jié)構(gòu),開發(fā)人員通過(guò)預(yù)留的接口插入代碼(做填空題)——把自己的錘子裝在流水線上,讓它砸核桃。
- 設(shè)計(jì)模式:復(fù)用解決方案;
- 設(shè)計(jì)模式提供了解決一類問(wèn)題的有效經(jīng)驗(yàn),復(fù)用這些經(jīng)驗(yàn)往往可以很好地解決問(wèn)題——看別人是怎么砸核桃的,依葫蘆畫瓢模仿一遍。
DI:依賴注入【IOC的底層】
?(3) AOP 編程的支持
通過(guò) Spring 提供的 AOP 功能,方便進(jìn)行面向切面的編程,許多不容易用 傳統(tǒng) OOP 實(shí)現(xiàn)的功能可以通過(guò) AOP 輕松應(yīng)付【面向切面編程】
在 Spring 中,開發(fā)人員可以從繁雜的事務(wù)管理代碼中解脫出來(lái),通過(guò)聲明 式方式靈活地進(jìn)行事務(wù)的管理,提高開發(fā)效率和質(zhì)量。
(4) 方便集成各種優(yōu)秀框架
Spring 不排斥各種優(yōu)秀的開源框架,相反 Spring 可以降低各種框架的使 用難度,Spring 提供了對(duì)各種優(yōu)秀框架(如 Struts,Hibernate、MyBatis)等 的直接支持。簡(jiǎn)化框架的使用。
Spring 像插線板一樣,其他框架是插頭,可以容易的組合到一起。需要使用哪 個(gè)框架,就把這個(gè)插頭放入插線板。不需要可以輕易的移除。
1.3 Spring 體系結(jié)構(gòu)
Spring 由 20 多個(gè)模塊組成,它們可以分為數(shù)據(jù)訪問(wèn)/集成(Data Access/Integration)、Web、面向切面編程(AOP, Aspects)、提供 JVM 的代理(Instrumentation)、消息發(fā)送(Messaging)、核心容器(Core Container)和測(cè)試(Test)。
第2章 IoC 控制反轉(zhuǎn)
控制反轉(zhuǎn)(IoC,Inversion of Control),是一個(gè)概念,是一種思想。指將傳統(tǒng)上由程序代碼直接操控的對(duì)象調(diào)用權(quán)交給容器,通過(guò)容器來(lái)實(shí)現(xiàn)對(duì)象的 裝配和管理??刂品崔D(zhuǎn)就是對(duì)對(duì)象控制權(quán)的轉(zhuǎn)移,從程序代碼本身反轉(zhuǎn)到了外部容器。通過(guò)容器實(shí)現(xiàn)對(duì)象的創(chuàng)建,屬性賦值,依賴的管理。
IoC 是一個(gè)概念,是一種思想,其實(shí)現(xiàn)方式多種多樣。當(dāng)前比較流行的實(shí)現(xiàn) 方式是依賴注入。應(yīng)用廣泛。
依賴:classA 類中含有 classB 的實(shí)例,在 classA 中調(diào)用 classB 的方法完 成功能,即 classA 對(duì) classB 有依賴。
Ioc 的實(shí)現(xiàn):
依賴注入:DI(Dependency Injection),程序代碼不做定位查詢,這些 工作由容器自行完成。
依賴注入 DI 是指程序運(yùn)行過(guò)程中,若需要調(diào)用另一個(gè)對(duì)象協(xié)助時(shí),無(wú)須在 代碼中創(chuàng)建被調(diào)用者,而是依賴于外部容器,由外部容器創(chuàng)建后傳遞給程序。
Spring 的依賴注入對(duì)調(diào)用者與被調(diào)用者幾乎沒有任何要求,完全支持對(duì)象 之間依賴關(guān)系的管理。
Spring 框架使用依賴注入(DI)實(shí)現(xiàn) IoC。
Spring 容器是一個(gè)超級(jí)大工廠,負(fù)責(zé)創(chuàng)建、管理所有的 Java 對(duì)象,這些 Java 對(duì)象被稱為 Bean。Spring 容器管理著容器中 Bean 之間的依賴關(guān)系, Spring 使用“依賴注入”的方式來(lái)管理 Bean 之間的依賴關(guān)系。使用 IoC 實(shí)現(xiàn) 對(duì)象之間的解耦和。
2.1 開發(fā)工具準(zhǔn)備
開發(fā)工具:idea2017 以上
依賴管理:maven3 以上
jdk:1.8 以上
需要設(shè)置 maven 本機(jī)倉(cāng)庫(kù):
2.2 Spring 的第一個(gè)程序
舉例:spring-quickstart
2.2.1 創(chuàng)建 maven 項(xiàng)目
?
2.2.2 引入 maven 依賴 pom.xml
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.0.9</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
2.2.3 定義接口與實(shí)體類
//接口創(chuàng)建
?public interface SomeService {
? ? ?void doSome();
?}
先寫一個(gè)接口, 接口里面有方法
下面的是實(shí)現(xiàn)類
再寫一個(gè)子包
讓SomeServiceImpl實(shí)現(xiàn)類實(shí)現(xiàn)SomeService接口
重寫方法
?完整代碼段:
package com.ambow.services.impl;
import com.ambow.services.SomeService;
//讓SomeServiceImpl實(shí)現(xiàn)類實(shí)現(xiàn)SomeService接口
public class SomeServiceImpl implements SomeService {
public SomeServiceImpl(){
System.out.println("========調(diào)用了SomeServiceImpl的無(wú)參構(gòu)造方法========");
}
@Override
public void doSome() {
System.out.println("=======doSome業(yè)務(wù)方法==========");
}
}
2.2.4 創(chuàng)建 Spring 配置文件
在 src/main/resources/目錄現(xiàn)創(chuàng)建一個(gè) xml 文件,文件名可以隨意,但 Spring 建議的名稱為 applicationContext.xml。
?選擇上述的創(chuàng)建方式會(huì)將頭文件自己編輯好,不用我們自己加入,方便快捷。
創(chuàng)建好之后在容器里面創(chuàng)建對(duì)象
spring 配置中需要加入約束文件才能正常使用,約束文件是 xsd 擴(kuò)展名。
<?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">
<!-- 創(chuàng)建bean的對(duì)象 Spring容器用來(lái)管理bean對(duì)象-->
<bean id="someService" class="com.ambow.services.impl.SomeServiceImpl"/>
</beans>
<bean />:用于定義一個(gè)實(shí)例對(duì)象。一個(gè)實(shí)例對(duì)應(yīng)一個(gè) bean 元素。
id【對(duì)象名】:該屬性是 Bean 實(shí)例的唯一標(biāo)識(shí),程序通過(guò) id 屬性訪問(wèn) Bean,Bean 與 Bean 間的依賴關(guān)系也是通過(guò) id 屬性關(guān)聯(lián)的。
class:指定該 Bean 所屬的類,注意這里只能是類,不能是接口。
2.2.5 定義測(cè)試類
在test里面創(chuàng)建一個(gè)對(duì)象原來(lái)測(cè)試?
?
使用的是ClassPathXml下的xml文件
將前面的xml文件導(dǎo)入
使用里面的getbean方法拿到容器
package com.ambow.test;
import com.ambow.services.SomeService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringTest {
@Test
public void test01(){
//1.獲取到Spring的容器
//使用技巧:連續(xù)按住shift兩次就可以看到類,ctrl+h可以查看ApplicationContext接口
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//2.從容器當(dāng)中取出對(duì)象
//此處的返回對(duì)象類型是已知的SomeService,使用的時(shí)候可以換回來(lái),原先的是object類型
SomeService someService = (SomeService) ctx.getBean("someService");
//3.使用對(duì)象,調(diào)用里面的方法
someService.doSome();
}
}
運(yùn)行結(jié)果:?
現(xiàn)在是容器幫助我們?nèi)?chuàng)建【new】對(duì)象
2.2.6 使用 spring 創(chuàng)建非自定義類對(duì)象
spring 配置文件加入 java.util.Date 定義:
<!--注冊(cè)非定義類的對(duì)象-->
<bean id="myDate" class="java.util.Date" />
MyTest 測(cè)試類中:
調(diào)用 getBean(“myDate”); 獲取日期類對(duì)象。
在前面的測(cè)試?yán)锩婕尤胍韵麓a
@Test
public void test02(){
//1.獲取到Spring的容器
//使用技巧:連續(xù)按住shift兩次就可以看到類,ctrl+h可以查看ApplicationContext接口
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//2.從容器當(dāng)中取出對(duì)象
//此處的返回對(duì)象類型是已知的SomeService,使用的時(shí)候可以換回來(lái),原先的是object類型
Date myDate = (Date) ctx.getBean("myDate");
//3.使用對(duì)象,調(diào)用里面的方法
System.out.println(myDate);
}
運(yùn)行結(jié)果:
?此處雖然我們沒有調(diào)用無(wú)參構(gòu)造方法,但是此處還是調(diào)用了該方法。
2.2.7 容器接口和實(shí)現(xiàn)類
ApplicationContext 接口(容器)
ApplicationContext 用于加載 Spring 的配置文件,在程序中充當(dāng)“容 器”的角色。其實(shí)現(xiàn)類有兩個(gè)。
帶有小耳機(jī)的哪些是抽象類,真正用到的是filesystemxml【文件的,但是不適合開發(fā),開發(fā)時(shí)每個(gè)人的電腦存放的文件地址都不一樣,不好維護(hù)】和classpathxml【類的,通過(guò)這個(gè)來(lái)創(chuàng)建容器】
A、 配置文件在類路徑下
若 Spring 配置文件存放在項(xiàng)目的類路徑下,則使用 ClassPathXmlApplicationContext 實(shí)現(xiàn)類進(jìn)行加載。
B、ApplicationContext 容器中對(duì)象的裝配時(shí)機(jī)
ApplicationContext 容器,會(huì)在容器對(duì)象初始化時(shí),將其中的所有對(duì)象一 次性全部裝配好。以后代碼中若要使用到這些對(duì)象,只需從內(nèi)存中直接獲取即 可。執(zhí)行效率較高。但占用內(nèi)存。
?案例測(cè)試:
C、使用 spring 容器創(chuàng)建的 java 對(duì)象
2.3 基于 XML 的 DI
舉例:項(xiàng)目 di-xml
2.3.1 注入分類
bean 實(shí)例在調(diào)用無(wú)參構(gòu)造器創(chuàng)建對(duì)象后,就要對(duì) bean 對(duì)象的屬性進(jìn)行初 始化。初始化是由容器自動(dòng)完成的,稱為注入。
根據(jù)注入方式的不同,常用的有兩類:set 注入、構(gòu)造注入。
(1) set 注入(掌握)
set 注入也叫設(shè)值注入是指,通過(guò) setter 方法傳入被調(diào)用者的實(shí)例。這種 注入方式簡(jiǎn)單、直觀,因而在 Spring 的依賴注入中大量使用。
A、 簡(jiǎn)單類型
package com.ambow.pojo;
public class Student {
private String name;
private int age;
//alt+insert出現(xiàn)快捷鍵創(chuàng)建tostring和其他方法
//加入set方法獲取name和age
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
創(chuàng)建 java.util.Date 并設(shè)置初始的日期時(shí)間:
<!--注冊(cè)非定義類的對(duì)象-->
<bean id="myDate" class="java.util.Date">
<property name="time" value="12143432412532"/>
</bean>
Spring 配置文件:
?測(cè)試方法:
@Test
public void test02(){
Date date = (Date) ctx.getBean("myDate");
System.out.println(date);
}
B、引用類型
當(dāng)指定 bean 的某屬性值為另一 bean 的實(shí)例時(shí),通過(guò) ref 指定它們間的引 用關(guān)系。ref 的值必須為某 bean 的 id 值。
<bean id="student" class="com.ambow.pojo.Student">
<property name="name" value="張三"/>
<property name="age" value="20"/>
<!-- 此處的學(xué)校為引用類型,使用需要使用ref -->
<property name="school" ref="school"/>
</bean>
<bean id="school" class="com.ambow.pojo.School">
<property name="name" value="北京大學(xué)"/>
<property name="address" value="北京"/>
</bean>
對(duì)于其它 Bean 對(duì)象的引用,使用標(biāo)簽的 ref 屬性
測(cè)試方法:
@Test
public void test01(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
Student student = (Student) ctx.getBean("student");
System.out.println(student);
}
(2) 構(gòu)造注入(理解)
構(gòu)造注入是指,在構(gòu)造調(diào)用者實(shí)例的同時(shí),完成被調(diào)用者的實(shí)例化。即, 使用構(gòu)造器設(shè)置依賴關(guān)系。
舉例 1:
<!-- 構(gòu)造注入 -->
<bean id="student1" class="com.ambow.pojo.Student">
<constructor-arg name="name" value="李四"/>
<constructor-arg name="age" value="19"/>
<constructor-arg name="school" value="student"/>
</bean>
<constructor-arg />標(biāo)簽中用于指定參數(shù)的屬性有:
-
name:指定參數(shù)名稱。
-
index:指明該參數(shù)對(duì)應(yīng)著構(gòu)造器的第幾個(gè)參數(shù),從 0 開始。不過(guò),該屬性 不要也行,但要注意,若參數(shù)類型相同,或之間有包含關(guān)系,則需要保證賦值順 序要與構(gòu)造器中的參數(shù)順序一致。
舉例 2:
@Test
public void test03(){
Student student = (Student) ctx.getBean("student1");
System.out.println(student);
}
最終的student類:
package com.ambow.pojo;
public class Student {
private String name;
private int age;
private School school;
//alt+insert出現(xiàn)快捷鍵創(chuàng)建tostring和其他方法
//加入無(wú)參構(gòu)造
public Student() {
}
public Student(String name, int age, School school) {
this.name = name;
this.age = age;
this.school = school;
}
//加入set方法獲取name和age
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setSchool(School school) {
this.school = school;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", school=" + school +
'}';
}
}
school類:
package com.ambow.pojo;
public class School {
private String name;
private String address;
public void setName(String name) {
this.name = name;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "School{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
}
使用構(gòu)造注入創(chuàng)建一個(gè)系統(tǒng)類 File 對(duì)象
2.3.2 引用類型屬性自動(dòng)注入
對(duì)于引用類型屬性的注入,也可不在配置文件中顯示的注入。可以通過(guò)為 標(biāo)簽設(shè)置 autowire 屬性值,為引用類型屬性進(jìn)行隱式自動(dòng)注入(默 認(rèn)是不自動(dòng)注入引用類型屬性)。根據(jù)自動(dòng)注入判斷標(biāo)準(zhǔn)的不同,可以分為兩 種:
-
byName:根據(jù)名稱自動(dòng)注入
-
byType: 根據(jù)類型自動(dòng)注入
(1) byName 方式自動(dòng)注入
當(dāng)配置文件中被調(diào)用者 bean 的 id 值與代碼中調(diào)用者 bean 類的屬性名相 同時(shí),可使用 byName 方式,讓容器自動(dòng)將被調(diào)用者 bean 注入給調(diào)用者 bean。容器是通過(guò)調(diào)用者的 bean 類的屬性名與配置文件的被調(diào)用者 bean 的 id 進(jìn)行比較而實(shí)現(xiàn)自動(dòng)注入的。
舉例:
這種是根據(jù)名字自動(dòng)注入
<bean id="student" class="com.ambow.pojo.Student" autowire="byName">
<property name="name" value="張三"/>
<property name="age" value="20"/>
<!-- 此處的學(xué)校為引用類型,使用需要使用ref -->
<!-- <property name="school" ref="school"/>-->
</bean>
接著測(cè)試:
@Test
public void test01(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
Student student = (Student) ctx.getBean("student");
System.out.println(student);
}
(2) byType 方式自動(dòng)注入
使用 byType 方式自動(dòng)注入,要求:配置文件中被調(diào)用者 bean 的 class 屬 性指定的類,要與代碼中調(diào)用者 bean 類的某引用類型屬性類型同源。即要么 相同,要么有 is-a 關(guān)系(子類,或是實(shí)現(xiàn)類)。但這樣的同源的被調(diào)用 bean 只能有一個(gè)。多于一個(gè),容器就不知該匹配哪一個(gè)了。
舉例:
<bean id="student2" class="com.ambow.pojo.Student" autowire="byType">
<property name="name" value="張三"/>
<property name="age" value="20"/>
<!-- 此處的學(xué)校為引用類型,使用需要使用ref -->
<!-- <property name="school" ref="school"/>-->
</bean>
<!--注冊(cè)非定義類的對(duì)象-->
<bean id="myDate" class="java.util.Date">
<property name="time" value="12143432412532"/>
</bean>
<bean id="school1" class="com.ambow.pojo.School">
<property name="name" value="北京大學(xué)"/>
<property name="address" value="北京"/>
</bean>
<!-- 構(gòu)造注入 -->
<bean id="student1" class="com.ambow.pojo.Student">
<constructor-arg name="name" value="李四"/>
<constructor-arg name="age" value="19"/>
<constructor-arg name="school" value="school1"/>
</bean>
測(cè)試類:
@Test
public void test04(){
Student student = (Student) ctx.getBean("student2");
System.out.println(student);
}
2.3.3 為應(yīng)用指定多個(gè) Spring 配置文件
在實(shí)際應(yīng)用里,隨著應(yīng)用規(guī)模的增加,系統(tǒng)中 Bean 數(shù)量也大量增加,導(dǎo) 致配置文件變得非常龐大、臃腫。為了避免這種情況的產(chǎn)生,提高配置文件的 可讀性與可維護(hù)性,可以將 Spring 配置文件分解成多個(gè)配置文件。
包含關(guān)系的配置文件:
多個(gè)配置文件中有一個(gè)總文件,總配置文件將各其它子文件通過(guò)<import />引入。在 Java 代碼中只需要使用總配置文件對(duì)容器進(jìn)行初始化即可。
舉例:
bean-school.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">
<!--注冊(cè)非定義類的對(duì)象-->
<bean id="myDate" class="java.util.Date">
<property name="time" value="12143432412532"/>
</bean>
<bean id="school1" class="com.ambow.pojo.School">
<property name="name" value="北京大學(xué)"/>
<property name="address" value="北京"/>
</bean>
</beans>
bean-student.xml文件:
autowire自動(dòng)注入
<?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="com.ambow.pojo.Student" autowire="byName">
<property name="name" value="張三"/>
<property name="age" value="20"/>
<!-- 此處的學(xué)校為引用類型,使用需要使用ref -->
<!-- <property name="school" ref="school"/>-->
</bean>
<!-- 構(gòu)造注入 -->
<bean id="student1" class="com.ambow.pojo.Student">
<constructor-arg name="name" value="李四"/>
<constructor-arg name="age" value="19"/>
<constructor-arg name="school" value="school1"/>
</bean>
<bean id="student2" class="com.ambow.pojo.Student" autowire="byType">
<property name="name" value="張三"/>
<property name="age" value="20"/>
<!-- 此處的學(xué)校為引用類型,使用需要使用ref -->
<!-- <property name="school" ref="school"/>-->
</bean>
</beans>
主配置文件:
<?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">
<import resource="bean-student.xml"/>
<import resource="bean-school.xml"/>
</beans>
?
整體的目錄結(jié)構(gòu)如上圖所示。?
Spring 配置文件:
也可使用通配符 * 。但,此時(shí)要求父配置文件名不能滿足*所能匹配的格 式,否則將出現(xiàn)循環(huán)遞歸包含。就本例而言,父配置文件不能匹配 spring- *.xml 的格式,即不能起名為 spring-total.xml。
測(cè)試代碼:
2.4 基于注解的 DI
舉例:di-annotation 項(xiàng)目
?1)導(dǎo)入依賴
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.26</version>
</dependency>
2)將前面的student與school類導(dǎo)入進(jìn)來(lái)
對(duì)于 DI 使用注解,將不再需要在 Spring 配置文件中聲明 bean 實(shí)例。
Spring 中使用注解,需要在原有 Spring 運(yùn)行環(huán)境基礎(chǔ)上再做一些改變。
需要在 Spring 配置文件中配置組件掃描器,用于在指定的基本包中掃描 注解。
PS:注解相當(dāng)于在原先的類上面做一個(gè)標(biāo)記,加標(biāo)記之后,spring在容器里面生成類的對(duì)象
?3)在resources文件夾里面創(chuàng)建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"
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 https://www.springframework.org/schema/context/spring-context.xsd">
<!--開啟注解開發(fā) base-package掃描的包,可以掃描多個(gè)包-->
<!-- 一般使用逗號(hào)或者空格或者;來(lái)隔開好幾個(gè)包,或者直接指明父包【這種情況下掃描的包較多就會(huì)浪費(fèi)資源】 -->
<context:component-scan base-package="com.ambow.pojo,com.ambow.mapper,com.ambow.service"/>
</beans>
指定多個(gè)包的三種方式:
1)使用多個(gè) context:component-scan 指定不同的包路徑
2)指定 base-package 的值使用分隔符
分隔符可以使用逗號(hào)(,)分號(hào)(;)還可以使用空格,不建議使用空格。
逗號(hào)分隔或者分號(hào)分隔
<?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 https://www.springframework.org/schema/context/spring-context.xsd">
<!--開啟組件掃描 base-package掃描的包,可以掃描多個(gè)包-->
<!-- 一般使用逗號(hào)或者空格或者;來(lái)隔開好幾個(gè)包,或者直接指明父包【這種情況下掃描的包較多就會(huì)浪費(fèi)資源】 -->
<context:component-scan base-package="com.ambow.pojo,com.ambow.mapper,com.ambow.service"/>
</beans>
3)base-package 是指定到父包名
base-package 的值表是基本包,容器啟動(dòng)會(huì)掃描包及其子包中的注解,當(dāng) 然也會(huì)掃描到子包下級(jí)的子包。所以 base-package 可以指定一個(gè)父包就可以。
<context:component-scan base-package="com.ambow"/>
或者最頂級(jí)的父包
<context:component-scan base-package="com"/>
但不建議使用頂級(jí)的父包,掃描的路徑比較多,導(dǎo)致容器啟動(dòng)時(shí)間變慢。指定 到目標(biāo)包和合適的。也就是注解所在包全路徑。例如注解的類在 com.bjpowernode.beans 包中
<context:component-scan base-package="com.ambow.pojo"/>
2.4.1 定義 Bean 的注解@Component(掌握)
? 需要在類上使用注解@Component,該注解的 value 屬性用于指定該 bean 的 id 值。
舉例:student類
package com.ambow.pojo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
//添加注解
@Component("myStudent")
public class Student {
private String name;
private int age;
private School school;
//alt+insert出現(xiàn)快捷鍵創(chuàng)建tostring和其他方法
public Student() {
}
public Student(String name, int age, School school) {
this.name = name;
this.age = age;
this.school = school;
}
//加入set方法獲取name和age
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setSchool(School school) {
this.school = school;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", school=" + school +
'}';
}
}
另外,Spring 還提供了 3 個(gè)創(chuàng)建對(duì)象的注解:【應(yīng)用于web開發(fā)里面】
-
@Repository 用于對(duì) DAO【持久層】 實(shí)現(xiàn)類進(jìn)行注解
-
@Service 用于對(duì) Service 【業(yè)務(wù)層】實(shí)現(xiàn)類進(jìn)行注解
-
@Controller 用于對(duì) Controller【控制層】 實(shí)現(xiàn)類進(jìn)行注解
這三個(gè)注解與@Component 都可以創(chuàng)建對(duì)象,但這三個(gè)注解還有其他的含義
- @Service 創(chuàng)建業(yè)務(wù)層對(duì)象,業(yè)務(wù)層對(duì)象可以加入事務(wù)功能,
- @Controller 注解創(chuàng)建的對(duì)象可以作為處理器接收用戶的請(qǐng)求。
- @Repository,@Service,@Controller 是對(duì)@Component 注解的細(xì)化,標(biāo)注不同層的對(duì)象。即持久層對(duì)象,業(yè)務(wù)層對(duì)象,控制層對(duì)象。
- @Component 不指定 value 屬性,bean 的 id 是類名的首字母小寫。
測(cè)試類測(cè)試
package com.ambow.test;
import com.ambow.pojo.School;
import com.ambow.pojo.Student;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AnnotationTest {
@Test
public void test01(){
ApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");
Student myStudent = (Student) cxt.getBean("myStudent");
System.out.println(myStudent);
}
}
??此處并未賦值。
注解
@Component("myStudent")
等價(jià)于
2.4.2 簡(jiǎn)單類型屬性注入@Value(掌握)
需要在屬性上使用注解@Value,該注解的 value 屬性用于指定要注入的 值。
使用該注解完成屬性注入時(shí),類中無(wú)需 setter。當(dāng)然,若屬性有 setter, 則也可將其加到 setter 上。
舉例:
student類:
package com.ambow.pojo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
//注解為硬編碼,編輯需要修改原來(lái)的代碼【使用在不經(jīng)常修改的地方可以使用注解】
//xml不需要重新修改代碼,不需要重新打包,但是大型的程序并不好開發(fā)。
//添加注解注入
//Service在業(yè)務(wù)層
//@Service("myStudent")
@Component("myStudent")
public class Student {
@Value("李四")
private String name;
@Value("18")
private int age;
private School school;
//alt+insert出現(xiàn)快捷鍵創(chuàng)建tostring和其他方法
public Student() {
}
public Student(String name, int age, School school) {
this.name = name;
this.age = age;
this.school = school;
}
//加入set方法獲取name和age
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setSchool(School school) {
this.school = school;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", school=" + school +
'}';
}
}
school類:
package com.ambow.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
//不給值默認(rèn)會(huì)將類名稱小寫
@Component("mySchool")
public class School {
@Value("北京大學(xué)")
private String name;
@Value("北京")
private String address;
public void setName(String name) {
this.name = name;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "School{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
}
測(cè)試類:
在原先的測(cè)試用例基礎(chǔ)之上書寫測(cè)試用例test02
@Test
public void test02(){
ApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");
School school = (School) cxt.getBean("mySchool");
System.out.println(school);
}
?
2.4.3 byType 自動(dòng)注入@Autowired(掌握)
此時(shí)的學(xué)生類里面的school屬性任然為空值
需要在引用屬性上使用注解@Autowired,該注解默認(rèn)使用按類型自動(dòng)裝 配 Bean 的方式。
使用該注解完成屬性注入時(shí),類中無(wú)需 setter。當(dāng)然,若屬性有 setter, 則也可將其加到 setter 上。
舉例:
package com.ambow.pojo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
//注解為硬編碼,編輯需要修改原來(lái)的代碼【使用在不經(jīng)常修改的地方可以使用注解】
//xml不需要重新修改代碼,不需要重新打包,但是大型的程序并不好開發(fā)。
@Component("myStudent")
public class Student {
@Value("李四")
private String name;
@Value("18")
private int age;
//為學(xué)校注入注解【指定類型注入】,Autowired默認(rèn)以類型注入
@Autowired
private School school;
//alt+insert出現(xiàn)快捷鍵創(chuàng)建tostring和其他方法
public Student() {
}
public Student(String name, int age, School school) {
this.name = name;
this.age = age;
this.school = school;
}
//加入set方法獲取name和age
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setSchool(School school) {
this.school = school;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", school=" + school +
'}';
}
}
注入完成之后繼續(xù)測(cè)試
可以看到此時(shí)的學(xué)校注入進(jìn)去了。?
2.4.4 byName 自動(dòng)注入@Autowired 與@Qualifier(掌握)
因?yàn)榍懊婢庉媠chool類的時(shí)候已經(jīng)將school的component屬性名編輯了,既是下面的內(nèi)容:
@Component("mySchool")
需要在引用屬性上聯(lián)合使用注解@Autowired 與@Qualifier。@Qualifier 的 value 屬性用于指定要匹配的 Bean 的 id 值。類中無(wú)需 set 方法,也可加到 set 方法上。
此時(shí)的名稱不可被修改,如果修改名稱則會(huì)報(bào)錯(cuò),Qualifier會(huì)找不到相關(guān)的名稱
舉例:
package com.ambow.pojo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
//注解為硬編碼,編輯需要修改原來(lái)的代碼【使用在不經(jīng)常修改的地方可以使用注解】
//xml不需要重新修改代碼,不需要重新打包,但是大型的程序并不好開發(fā)。
//添加注解注入
//Service在業(yè)務(wù)層
//@Service("myStudent")
@Component("myStudent")
public class Student {
@Value("李四")
private String name;
@Value("18")
private int age;
//另外一種注解【指定名稱注入】,以名字注入,必須兩個(gè)一起搭配使用,否則將會(huì)報(bào)錯(cuò),無(wú)法注入。
@Autowired
//此時(shí)如果學(xué)校類的名字修改之后將會(huì)報(bào)錯(cuò),
@Qualifier("mySchool")
private School school;
//alt+insert出現(xiàn)快捷鍵創(chuàng)建tostring和其他方法
public Student() {
}
public Student(String name, int age, School school) {
this.name = name;
this.age = age;
this.school = school;
}
//加入set方法獲取name和age
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setSchool(School school) {
this.school = school;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", school=" + school +
'}';
}
}
@Autowired 還有一個(gè)屬性 required,默認(rèn)值為 true,表示當(dāng)匹配失敗 后,會(huì)終止程序運(yùn)行。若將其值設(shè)置為 false,則匹配失敗,將被忽略,未匹配 的屬性值為 null。
2.4.5 JDK 注解@Resource 自動(dòng)注入(掌握)
Spring 提供了對(duì) jdk 中@Resource 注解的支持。@Resource 注解既可以 按名稱匹配 Bean,也可以按類型匹配 Bean。默認(rèn)是按名稱注入。使用該注 解,要求 JDK 必須是 6 及以上版本。@Resource 可在屬性上,也可在 set 方 法上。
(1) byType 注入引用類型屬性
@Resource 注解若不帶任何參數(shù),采用默認(rèn)按名稱的方式注入,按名稱不 能注入 bean,則會(huì)按照類型進(jìn)行 Bean 的匹配注入。
舉例:
package com.ambow.pojo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Component("myStudent")
public class Student {
@Value("李四")
private String name;
@Value("18")
private int age;
//Resource按照名字注入,先按照名稱注入,找不到在按照類型注入
@Resource
private School school;
//alt+insert出現(xiàn)快捷鍵創(chuàng)建tostring和其他方法
public Student() {
}
public Student(String name, int age, School school) {
this.name = name;
this.age = age;
this.school = school;
}
//加入set方法獲取name和age
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setSchool(School school) {
this.school = school;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", school=" + school +
'}';
}
}
運(yùn)行測(cè)試:?
(2) byName 注入引用類型屬性
@Resource 注解指定其 name 屬性,則 name 的值即為按照名稱進(jìn)行匹 配的 Bean 的 id。
舉例:
package com.ambow.pojo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Component("myStudent")
public class Student {
@Value("李四")
private String name;
@Value("18")
private int age;
//添加屬性值就會(huì)按照屬性來(lái)注入,修改名稱會(huì)報(bào)錯(cuò)。
//測(cè)試一下另外一個(gè)類【假設(shè)為Score,名稱和學(xué)校的相同時(shí)】,其另外一類的屬性和學(xué)校類相同,名稱相同時(shí),引用時(shí)會(huì)報(bào)錯(cuò),不會(huì)注入另外一個(gè)類【假設(shè)為Score】
@Resource(name = "mySchool")
private School school;
//alt+insert出現(xiàn)快捷鍵創(chuàng)建tostring和其他方法
public Student() {
}
public Student(String name, int age, School school) {
this.name = name;
this.age = age;
this.school = school;
}
//加入set方法獲取name和age
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setSchool(School school) {
this.school = school;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", school=" + school +
'}';
}
}
Score類:
package com.ambow.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
//默認(rèn)的會(huì)是下面這種形式的命名
@Component("myScore")
//此處要是測(cè)試的話需要是下面的這種形式
//@Component("mySchool")
public class Score {
@Value("大潤(rùn)發(fā)商店")
private String name;
@Value("長(zhǎng)清區(qū)")
private String address;
}
運(yùn)行測(cè)試會(huì)報(bào)錯(cuò)
2.4.6 注解與 XML 的對(duì)比
注解優(yōu)點(diǎn)是:
方便
直觀
高效(代碼少,沒有配置文件的書寫那么復(fù)雜)。
其弊端也顯而易見:以硬編碼的方式寫入到 Java 代碼中,修改是需要重新 編譯代碼的。
XML 方式優(yōu)點(diǎn)是:
配置和代碼是分離的
在 xml 中做修改,無(wú)需編譯代碼,只需重啟服務(wù)器即可將新的配置加載。
XML 的缺點(diǎn)是:編寫麻煩,效率低,大型項(xiàng)目過(guò)于復(fù)雜。
第3章?傳統(tǒng)案例實(shí)現(xiàn)與spring對(duì)比
3.1? 項(xiàng)目目錄
?
3.2?person類
傳統(tǒng)的是創(chuàng)建對(duì)象
?后面一段代碼
?傳統(tǒng)的方式如果要修改程序就需要重新寫這種硬編碼,修改繁瑣。是一種強(qiáng)耦合方式,升級(jí)不方便。
3.3?在pom.xml文件導(dǎo)入下面的依賴
3.4?寫一個(gè)配置文件?
?寫入以下信息
?如果要修改的話,此時(shí)的可以直接修改bean里面的對(duì)象,可以修改為car
3.5? 利用spring優(yōu)化的地方
前面自己創(chuàng)建的交通工具類,選擇直接讓容器創(chuàng)建即可,我們不再需要自己創(chuàng)建。?
?包括前面的person類,也可以不用創(chuàng)建,直接在配置文件里面創(chuàng)建person即可
?此處給的person的值為李四,ref引用上面的v1里面的交通工具。
?修改的部分
?原先的在容器里面創(chuàng)建
?程序的耦合度就降低了
總結(jié)
以上就是今天的內(nèi)容~
歡迎大家點(diǎn)贊??,收藏?,轉(zhuǎn)發(fā)??,
如有問(wèn)題、建議,請(qǐng)您在評(píng)論區(qū)留言??哦。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-632671.html
最后:轉(zhuǎn)載請(qǐng)注明出處!?。?/strong>文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-632671.html
到了這里,關(guān)于IDEA項(xiàng)目實(shí)踐——Spring框架簡(jiǎn)介,以及IOC注解的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!