1.Spring是什麼?
Spring是一個JavaEE輕量級的一站式開發框架。
JavaEE: 就是用於開發B/S的程式。(企業級)
輕量級:使用最少程式碼啟動框架,然後根據你的需求選擇,選擇你喜歡的模組使用。
重量級:早期有的EJB,開發一個HelloWorld程式都需要引入EBJ的全部模組
一站式:Spring框架提供涵蓋了JavaEE開發的表示層,服務層,持久層的所有元件功能。也就是說,原則上,學完一套Spring框架,不用其他框架就可以完成網站一條流程的開發。但是Spring仍然可以和其他的框架無縫整合。
2.Spring的優點
輕量:Spring 是輕量的,就是除核心模組(4個jar),其他模組由開發者自由選擇使用,同時支援整合其他框架。也可以稱為就是可插拔式開發框架,像插頭和插座一樣,插上就用。這就是Spring框架核心理念(Ioc)。
控制反轉:Spring通過控制反轉實現了鬆散耦合,物件們給出它們的依賴,而不是建立或查詢依賴的物件們。
面向切面的程式設計(AOP):Spring支援面向切面的程式設計,並且把應用業務邏輯和系統服務分開。
容器:Spring 包含並管理應用中物件的生命週期和配置。
MVC框架:Spring的WEB框架是個精心設計的框架,是Web框架的一個很好的替代品。
事務管理:Spring 提供一個持續的事務管理介面,可以擴充套件到上至本地事務下至全域性事務(JTA)。
異常處理:Spring 提供方便的API把具體技術相關的異常(比如由JDBC,Hibernate or JDO丟擲的)轉化為一致的unchecked 異常。
3.Spring的作用
Spring強調的理念是,輕量級。Spring的輕量級主要體現在模組的可插拔,Spring提供的功能模組,除了核心模組以外,開發人員可以選擇性使用。所以,Spring框架在現實開發中,主要的功能用於整合各種開發框架開發專案。
4.Spring框架包
Spring官方網站:https://spring.io/
4.1 下載
Spring官方提供的Maven方式的專案下載:https://start.spring.io/
但是基於簡單入門的原則,我們要通過匯入包的方式來學習。需要下載框架的zip包
地址為:http://repo.springsource.org/libs-release-local/org/springframework/spring/
4.2 目錄說明
根目錄:
jar包:
包說明:
包名 | 說明 |
spring-aop-4.3.2.RELEASE.jar | 實現了AOP的支援 |
spring-aspects-4.3.2.RELEASE.jar | AOP框架aspects支援包 |
spring-beans-4.3.2.RELEASE.jar | 核心支撐包,實現了處理基於xml物件存取 |
spring-context-4.3.2.RELEASE.jar | 核心支撐包,實現了Spring物件容器 |
spring-context-support-4.3.2.RELEASE.jar | 容器操作擴充套件包,擴充套件了一些常用的容器物件的設定功能 |
spring-core-4.3.2.RELEASE.jar | 核心支撐包,Spring的核心 |
spring-expression-4.3.2.RELEASE.jar | 核心支撐包,實現了xml對Spring表示式的支援 |
spring-instrument-4.3.2.RELEASE.jar | 提供了一些類載入的的工具類 |
spring-instrument-tomcat-4.3.2.RELEASE.jar | 提供了一些tomcat類載入的的工具類,實現對應Tomcat服務的呼叫 |
spring-jdbc-4.3.2.RELEASE.jar | SpringJDBC實現包,一個運算元據庫持久層的子框架 |
spring-jms-4.3.2.RELEASE.jar | 整合jms的支援,jms:Java訊息服務。 |
spring-messaging-4.3.2.RELEASE.jar | 整合messaging api和訊息協議提供支援 |
spring-orm-4.3.2.RELEASE.jar | ORM框架整合包,實現了Hibernate,IBatis,JDO的整合。 |
spring-oxm-4.3.2.RELEASE.jar | Spring OXM對主流O/X Mapping框架做了一個統一的抽象和封裝。就是對應XML讀寫框架的支援 |
spring-test-4.3.2.RELEASE.jar | Spring整合JUnit測試 |
spring-tx-4.3.2.RELEASE.jar | 事務代理的支援 |
spring-web-4.3.2.RELEASE.jar | SpringWeb通用模組 |
spring-webmvc-4.3.2.RELEASE.jar | SpringMVC子框架 |
spring-webmvc-portlet-4.3.2.RELEASE.jar | Spring對門戶技術(portlet)的支援 |
spring-websocket-4.3.2.RELEASE.jar | Spring對websocket的支援 |
注:紅色部分為基礎核心包,使用Spring必須匯入
5.入門例項
Spring之所以可以實現模組的可插拔是支援依賴注入,所謂的依賴注入/控制反轉就是不用new就可以建立物件。
使用Spring框架不用new建立一個物件:
1.建立專案並匯入jar包:將Spring的基礎支撐包和依賴的日誌包複製到lib檔案下,並且加入專案中
2.建立配置檔案
在專案的src下面建立配置檔案applicationContext.xml中並完成配置檔案的約束
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> </beans>
3.建立物件到Spring容器中
建立一個類
package com.gjs.service; public class HelloSpringService { public void say() { System.out.println("你好!Spring"); } }
往applicationContext.xml配置檔案中加入配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- <bean id="" class = ""> 配置讓spring管理類的物件的建立 id : 唯一標識 class :被管理類的全限定名 --> <bean id="HelloSpringService" class="com.gjs.service.HelloSpringService"/> </beans>
測試類, 使用getBean方法獲得容器中的物件。
package com.gjs.test; import static org.junit.Assert.*; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.gjs.service.HelloSpringService; public class TestSpring { @Test public void testName() throws Exception { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); HelloSpringService helloSpringService = context.getBean("HelloSpringService",HelloSpringService.class); helloSpringService.say(); } }
6.Spring容器的兩個實現
ClassPathXmlApplicationContext:通過classpath路徑(相對路徑)直接獲得載入的xml檔案(推薦使用)
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
FileSystemXmlApplicationContext:通過檔案路徑(絕對路徑)來獲得載入的xml檔案。
ApplicationContext context = new FileSystemXmlApplicationContext("D:\\java\\eclipse-workspace\\spring1\\src\\applicationContext.xml");
8.控制反轉(IOC)和依賴注入(DI)(A)
DI:Dependency Injection(依賴注入):
依賴注入是指Spring建立物件的過程中,將物件依賴屬性(簡單值,集合,物件)通過配置設值給該物件。
IoC:Inverse of Control(控制反轉):
Spring號稱是一個可以實現模組可插拔的JavaEE開發框架。而實現程式可插拔的核心理念就是控制反轉。所謂的控制反轉,就是將程式碼的呼叫權從呼叫方轉移給被呼叫方(服務提供方)。不用修改呼叫方的的程式碼,只要修改配置檔案就實現物件的切換。
讀作“反轉控制”,更好理解,它不是什麼技術,而是一種設計思想,好比於MVC。就是將原本在程式中手動建立物件的控制權,交由Spring框架來管理。
正控:若呼叫者需要使用某個物件,其自身就得負責該物件的建立。
反控:呼叫者只管負責從Spring容器中獲取需要使用的物件,不關心物件的建立過程,也就是把建立物件的控制權反轉給了Spring框架。
控制反轉(Ioc),就是依賴注入加上面向介面的程式設計思想的實現
示例:
整體結構:
CustomService介面:
package com.gjs.service; public interface CustomeService { public void say(); }
實現類CustomServiceImpl1:
package com.gjs.service.impl; import com.gjs.service.CustomeService; public class CustomServiceImpl1 implements CustomeService { @Override public void say() { System.out.println("CustomerServiceImpl1.say()"); } }
實現類CustomServiceImpl2:
package com.gjs.service.impl; import com.gjs.service.CustomeService; public class CustomServiceImpl2 implements CustomeService { @Override public void say() { System.out.println("CustomerServiceImpl2.say()"); } }
呼叫方 CustomClient:
package com.gjs.client; import com.gjs.service.CustomeService; public class CustomClient { //1.宣告一個介面引用型別 private CustomeService customeService; //2.spring的依賴注入(DI)需要有一個set方法 public void setCustomeService(CustomeService customeService) { this.customeService = customeService; } public void say() { customeService.say(); } }
配置檔案 applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- <bean id="" class = ""> 配置讓spring管理類的物件的建立 id : 唯一標識 class :被管理類的全限定名 --> <bean id="client" class="com.gjs.client.CustomClient"> <!-- 依賴注入(DI) :注入被呼叫方 <property name="" value/ref=""/> 位置: name : 是set方法確定的屬性,不是成員變數 確定屬性 : setXxx 方法去掉set字首 ,剩餘部分首字母小寫 引數: value : 值型別注入(字串,基本資料型別) ref :引用資料型別(物件), 對應bean的id --> <property name="customeService" ref="ServiceImpl1"/> </bean> <bean id="ServiceImpl1" class="com.gjs.service.impl.CustomServiceImpl1"/> <bean id="ServiceImpl2" class="com.gjs.service.impl.CustomServiceImpl2"/> </beans>
測試類:
package com.gjs.test; import static org.junit.Assert.*; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.gjs.client.CustomClient; import com.gjs.service.CustomeService; public class TestSpring { @Test public void testName() throws Exception { //1.讀取配置檔案,建立Spring容器 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); //獲取呼叫方 CustomClient物件 CustomClient client = context.getBean("client", CustomClient.class); //呼叫CustomClient物件的say()方法 client.say(); } }
應用:
Spring框架又被稱為容器框架,即通過控制反轉將各個框架的物件建立交給Spring管理,然後通過依賴注入在層之間傳遞引數整合框架,並達到低耦合的目的。
9.標籤說明
9.1 bean標籤
作用:用於宣告一個類,在啟動Spring框架的時候根據該配置的類建立物件到容器裡面
<bean id="someBean" class="com.gjs.pojo.SomeBean" scope="prototype"></bean>
id:設定物件名(唯一識別符號)(推薦使用)
name:設定物件名(唯一識別符號),與id的區別是可以有多個名稱,每個名稱用逗號隔開。
class:指定物件對應的類
scope:用於設定的物件的作用範圍,可選引數如下:
在Web開發的三層架構中的使用
Web層:一般都是多例
Service層 :單例
DAO層 :單例
9.2 alias 別名標籤
作用:為已配置的bean設定別名
bean id="user" name="test" class="com.gjs.pojo.User"/>
<alias name="user" alias="user1"/>
name:必要屬性, 代表為哪一個bean配置別名, 此屬性的值為其他bean標籤的id或name屬性值
alias: 必要屬性,命名的別名
10.例項化Bean的四種方式
1.構造器例項化(無引數構造器):(最常用)
public class SomeBean { public SomeBean() { System.out.println("SomeBean.SomeBean()"); } }
<bean id="someBean" class="com.gjs.pojo.SomeBean"/>
2.通過靜態方法工廠建立(C)
public class SomeBean { public SomeBean() { System.out.println("SomeBean.SomeBean()"); } } public class SomeBeanFacotry { //靜態工廠方法 public static SomeBean getSomeBean() { System.out.println("執行靜態工廠方法"); return new SomeBean(); } }
<bean id="someBean" class="com.gjs.pojo.SomeBeanFacotry" factory-method="getSomeBean"/>
3.通過實體工廠建立(C)
public class SomeBean { public SomeBean() { System.out.println("SomeBean.SomeBean()"); } } public class SomeBeanFacotry { //例項工廠方法 public SomeBean getSomeBean() { System.out.println("執行例項工廠方法"); return new SomeBean(); } }
<bean id="someBeanfactory" class="com.gjs.pojo.SomeBeanFactory"/>
或
<bean id="someBean" factory-bean="someBeanfactory" factory-method="getSomeBean"/>
4.實現FactoryBean介面例項化:例項工廠變種
實現FactoryBean介面,MyBatis和Spring整合就是使用的這種方式。此種方式,如果沒有使用Bean對應的物件,Spring就不會自動建立,只有在使用的時候Spring才會建立對應的物件
public class SomeBean { public SomeBean() { System.out.println("SomeBean4.SomeBean4()"); } } public class SomeBeanObjectFactory implements FactoryBean<SomeBean>{ //返回的泛型型別對應的物件 @Override public SomeBean getObject() throws Exception { SomeBean bean = new SomeBean(); return bean; } }
<bean id="someBean" class="cn.zj.domian.SomeBeanObjectFactory"/>
11.初始化和銷燬方法
<bean id="someBean" class="......"
<init-method="該類中初始化方法名"/>
<destroy-method="該類中銷燬方法名"/>
</bean>
init-method:bean生命週期初始化方法,物件建立後就進行呼叫
destroy-method:容器被銷燬的時候,如果bean被容器管理,會呼叫該方法。
12.依賴注入的四種方法
1.setter注入,(屬性注入)(常用)
使用setter注入:
1,使用bean元素的<property>子元素設定;
1.簡單型別值,直接使用value賦值;
2.引用型別,使用ref賦值;
3.集合型別,直接使用對應的集合型別元素即可。
2,spring通過屬性的set方法注入值;
3,在配置檔案中配置的值都是string,spring可以自動的完成型別的轉換
示例:
員工類
public class Employee { private Integer age; private String name; private Department dept; public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Department getDept() { return dept; } public void setDept(Department dept) { this.dept = dept; } @Override public String toString() { return "Employee [age=" + age + ", name=" + name + ", dept=" + dept + "]"; } }
部門類
public class Department { private Integer id; private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
配置檔案
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 員工 --> <bean id="employee" class="com.gjs.pojo.Employee" > <!-- setter方法注入: 屬性注入 <property name="" value=""> name : 屬性名稱 value : 基本資料型別+String型別的值注入 ref : 引用型別(物件型別)的注入 value 和ref 只能二選一 --> <property name="age" value="18"></property> <property name="name" value="張三"></property> <property name="dept" ref="dept"></property> </bean> <!-- 部門 --> <bean id="dept" class="com.gjs.pojo.Department" > <property name="id" value="1"/> <property name="name" value="開發部"/> </bean> </beans>
2.構造器注入
使用bean元素的<constructor-arg>子元素設定:
1.預設情況下,constructor-arg的順序就是構造器引數的順序
2. constructor-arg的屬性
name : 構造方法引數的名稱
index :引數的位置從 0 開始
value :值型別注入
ref :引用型別注入
type : 引數的資料型別
3.一般在一個類必須依賴另一個類才能正常執行時,才用構造器注入
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 配置部門 --> <bean id="department" class="com.gjs.pojo.Department"> <constructor-arg name="id" value="2"/> <constructor-arg name="name" value="研發部"/> </bean> <!-- 配置員工 --> <bean id="emp" class="com.gjs.pojo.Employee"> <!-- 依賴注入 :構造器注入 --> <constructor-arg name="id" value="1"/> <constructor-arg name="name" value="張三"/> <constructor-arg name="dept" ref="department"/> </bean> </beans>
3.p名稱空間注入
使用p名稱空間注入先在約束上面引入 p標籤
xmlns:p="http://www.springframework.org/schema/p"
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 配置部門 --> <bean id="department" class="com.gjs.pojo.Department" p:id="3" p:name="銷售部"/> <!-- 配置員工 --> <bean id="emp" class="com.gjs.pojo.Employee" p:id="1" p:name="張三" p:dept-ref="department"/> </beans>
4.集合型別值注入
用於處理:
1.鍵值對 Map 、Properties
2.陣列
3.集合Set、List
public class CollectionBean { private Set<String> set; private List<String> list; private String[] array; private Map<String, String> map; private Properties prop; //讀取本地 xxx.properties檔案(本質就是一個Map集合) }
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="collectionBean" class="cn.zj.spring.pojo.CollectionBean"> <!-- setter(屬性)方法注入 --> <!-- 1.陣列 --> <property name="arr"> <array> <value>AAA</value> <value>BBB</value> </array> </property> <!-- 2.set集合 --> <property name="set" > <set> <value>AAA</value> <value>AAA</value> <value>BBB</value> </set> </property> <!-- 3.list集合 --> <property name="lsit"> <list> <value>list1</value> <value>list1</value> <value>list2</value> </list> </property> <!-- 4. map集合 --> <property name="map"> <map> <entry key="key1" value="value1"/> <entry key="key2" value="value2"/> </map> </property> <!-- 5.properties 集合 --> <property name="prop"> <props> <prop key="propKey1">propValue1</prop> <prop key="propKey2">propValue2</prop> </props> </property> </bean> </beans>
13.獲得properties檔案的值
1.匯入名稱空間方法
將名稱空間和約束重新拷貝一份,將對於的全部替換成 context,然後關聯context本地schema約束
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd "> </beans>
2.匯入Mysql驅動包和druid連線池jar包
3.applicationContext.xml配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd "> <!-- 使用context 讀取配置檔案到spring容器中 <context:property-placeholder location=""/> location : db.properties檔案的位置,必須加上 classpath: 作為字首 --> <context:property-placeholder location="classpath:db.properties"/> <!-- 建立阿里巴巴druid連線池 --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close" > <!-- 屬性注入 setter方法注入--> <property name="driverClassName" value="${jdbc.driverClassName}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> <!-- 最大連線數 --> <property name="maxActive" value="${jdbc.maxActive}"/> </bean> </beans>
測試程式碼
@Test public void testSave() throws Exception { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); DataSource dataSource = context.getBean(DataSource.class, "dataSource"); Connection conn = dataSource.getConnection(); System.out.println("資料庫連線物件:"+conn); }