一、Spring架構
1.1 Spring架構是什麼
- Spring是一種容器架構,用于配置各個元件(bean)并且維護各個元件bean之間的關系
- Spring架構可以管理Web層,業務層,DAO層,持久層。
- Spring提倡面向接口程式設計,配合DI技術可以實作層與層的解耦(主要是WEB層和業務層)
- Spring架構圖
老闆:不懂spring還來做項目?建議離職一、Spring架構二、裝配Bean
1.2 一個簡單的spring項目
目錄結構
- 引入spring的開發包(最小配置spring.jar以及日志包common-logging.jar)
- 建立spring的一個核心檔案ApplicationContext.xml,該檔案一般放在src目錄下,該檔案中引入xsd檔案,可以自定義檔案名。
TestSpring
|---src
|---com.netease
| |---Service
| |---HelloService.java
| |---ByeService.java
| |---Test
| |---TestService.java
|---ApplicationContext.xml
External Libraries
|--- spring.jar
|--- common-logging.jar
|--- ...
代碼詳情
package com.netease.Service;
public class HelloService {
private String name;
private ByeService byeService; /** 引用了一個ByeService*/
public String getName() { return name;}
public void setName(String name) { this.name = name;}
public ByeService getByeService() { return byeService;}
public void setByeService(ByeService byeService) { this.byeService = byeService;}
public void sayHello() {
System.out.println("hello "+name);
}
}
package com.netease.Service;
public class ByeService {
private String name;
public String getName() { return name;}
public void setName(String name) {this.name = name;}
public void sayBye() {
System.out.println("Bye " + name);
}
}
package com.netease.Test;
import com.netease.Service.HelloService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestService {
public static void main(String[] args) {
/*通過反射機制,在Spring容器中生成對象*/
/*如果%%.xml放在某個包下,則就變為<包名+檔案名>*/
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("ApplicationContext.xml");
HelloService helloService = (HelloService) applicationContext.getBean("helloService");
helloService.sayHello();
helloService.getByeService().sayBye();
}
}
Spring核心容器檔案ApplicationContext.xml
- 在容器檔案中配置Bean(Bean有可能是以下各種類型service/dao/domain/action/資料源)
- 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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<--注意Spring如何配置Bean以及如何維護Bean之間的依賴-->
<bean id="helloService" class="com.netease.Service.HelloService">
<--注入屬性值-->
<property name="name">
<value>Today</value>
</property>
<--維護Bean之間依賴,ref指向下一個Bean-->
<property name="byeService" ref="byeService"/>
</bean>
<bean id="byeService" class="com.netease.Service.ByeService">
<property name="name">
<value>Yesterday</value>
</property>
</bean>
</beans>
1.3 Spring架構運作原理圖
- Spring架構什麼時候被加載,Spring中配置的bean怎樣被建立,Bean與Bean之間的關系如何維護
老闆:不懂spring還來做項目?建議離職一、Spring架構二、裝配Bean
1.4 IOC與DI是什麼
-
IOC(Inverse Of Controll ) 控制反轉:
所謂控制反轉就是把建立對象(bean),和維護對象(bean)的關系的權利從程式中轉移到spring的容器(applicationContext.xml),而程式本身不再維護.
-
DI(Dependency Injection) 依賴注入:
實際上DI和IOC是同一個概念,Spring設計者認為DI更準确表示Spring核心技術
二、裝配Bean
2.1 容納Bean
ApplicationContext方式
-
ApplicationContext ac = new
ClassPathXmlApplicationContext(“com/netease/bean.xml”)
- 這句話執行時,不僅執行個體化了該容器,其中配置的所有scope為singleton的bean全部通過反射機制被執行個體化,scope為prototype的bean不會被執行個體化
其他三種加載方式
- ClassPathXmlApplicationContext:從類路徑中加載。
- FileSystemXmlApplicationContext:從檔案系統加載,需要全路徑
- XmlWebApplicationContext:從web系統中加載。
好處:預先加載,速度快;缺點:耗記憶體
Bean的作用域,即scope
Bean工廠方式
-
BeanFactory factory = new XmlBeanFactory(new
ClassPathResource(“com/netease/bean.xml”))
- 這句話執行時,僅執行個體化了該容器,容器中的bean不被執行個體化,隻有當你使用factory.getBean("***")擷取某個bean時,才執行個體化該bean對應的對象。類似于延遲執行個體化
- 好處:節約記憶體;缺點:速度慢
- 一般沒有特殊要求,都采用ApplicationContext方式執行個體化(90%),移動端可采用Bean工廠方式
2.2 Bean生命周期
完整生命周期步驟如下(通常隻用到加粗的幾步):
- 執行個體化:程式加載ApplicationContext檔案,并把bean(scope=singleton)執行個體化到記憶體
- 設定屬性:調用set方法設定bean中指定的屬性 如果你實作了BeanNameAware接口, 則可以通過BeanName
- 如果你實作了BeanFactoryAware接口,則可以擷取BeanFactory
- 如果你實作了ApplicationContextAware接口,則可以擷取ApplicationContext
- 如果bean和一個後置處理器關聯,則會自動去調用 postProcessBeforeInitialization()方法
- 如果你實作InitializingBean接口,則會調用afterPropertiesSet()方法
- 如果設定了,則可以在bean檔案中定義自己的初始化方法init.
-
如果bean和一個後置處理器關聯,則會自動去調
postProcessAfterInitialization()方法
- 使用bean 容器關閉
- 可以通過實作DisposableBean接口來調用方法 destory,用來關閉資源等
- 可以在 調用定制的銷毀方法destroy
ApplicationContext方式
Bean工廠方式
2.3 裝配Bean
2.3.1 什麼是裝配Bean
告訴容器有哪些Bean以及容器如何使用依賴注入将它們配合在一起。
2.3.2 裝配方法
- 在XML進行顯式配置
- 在Java中進行顯示配置
- 隐式的bean發現機制和自動裝配
2.3.3 面向XML的裝配方法
2.3.3.1 添加一個Bean
- 基本配置:一個bean ID + 全稱類名
<beans>
<bean id="foo" class="...Foo"/>
<bean id="bar" class="...Bar"/>
</beans>
- scope屬性
<beans>
<bean id="foo" scope="prototype/singleton" class="...Foo"/>
<bean id="bar" class="...Bar"/>
</beans>
注意盡量使用預設的singleton,以防占用太大記憶體,影響程式性能
init-method 和destroy-method屬性
用途:在Spring執行個體化或者銷毀bean時做一些處理工作
使用方法:
- 聲明方式:在XML檔案中先聲明該Bean擁有的初始化和銷毀方法的函數名。在bean.java中實作init和destroy方法,函數名可自定義
- 标簽方式:不需要在xml檔案中聲明初始化和銷毀方法,在bean.java中采用标簽方式聲明初始化和銷毀方法
@PostConstruct
public void ini(){…}
@PreDestroy
public void destroy(){…}
其他進行初始化和銷毀處理的方法:
Spring還提供了兩個接口供bean.java使用,來進行執行個體化或者銷毀時的處理,但不推薦
2.3.3.2 通過set方法注入屬性和依賴
通過元素的子元素注入屬性和依賴
- 注入簡單屬性(基本類型和String)
<bean id="foo" class="...Foo">
<property name="name">
<value>tom</value>
</property>
</bean>
注入依賴
- 引用其他的Bean
<bean id="foo" class="...Foo">
<property name="name">
<ref bean="bar">
</property>
</bean>
<bean id="bar" class="...Bar">
</bean>
- 内部bean
<bean id="foo" class="...Foo">
<property name="bar">
<bean class="...Bar">...</bean>
</property>
</bean>
- 注入集合屬性(數組,List,Set,Map)
設定null
<property name="barlist">
<null/>
</property>
數組
<-- 給數組注入值 -->
<property name="empName">
<list>
<value>小明</value>
<value>李雷</value>
<value>韓梅梅</value>
</list>
</property>
List
<-- 給list注入值 list 中可以有相等的對象 -->
<property name="empList">
<list>
<ref bean="emp2" />
<ref bean="emp1"/>
<ref bean="emp1"/>
</list>
</property>
Set
<-- 給set注入值 set不能有相同的對象 -->
<property name="empsets">
<set>
<ref bean="emp1" />
<ref bean="emp2"/>
<ref bean="emp2"/>
</set>
</property>
Map
<-- 給map注入值隻要key不同即可 -->
<property name="empMaps">
<map>
<entry key="11" value-ref="emp1" />
<entry key="22" value-ref="emp2"/>
<entry key="33" value-ref="emp1"/>
</map>
</property>
property
<property name="pp">
<props>
<prop key="pp1">abcd</prop>
<prop key="pp2">hello</prop>
</props>
</property>
Bean的繼承
- public class Student有name和age兩個屬性
- public class Gradate extends
- Student 有degree屬性 在ApplicationContext檔案中展現配置
即student中配置過的屬性graduate可以不配置 如果配置,則會覆寫父類的屬性
<-- 配置一個學生對象 -->
<bean id="student" class="com.hsp.inherit.Student">
<property name="name" value="順平" />
<property name="age" value="30"/>
</bean>
<-- 配置Grdate對象 -->
<bean id="grdate" parent="student" class="com.hsp.inherit.Gradate">
<-- 如果自己配置屬性name,age,則會替換從父對象繼承的資料 -->
<property name="name" value="小明"/>
<property name="degree" value="學士"/>
</bean>
2.3.3.3 通過構造器注入屬性
通過元素的子元素注入屬性
<bean id="test" class ="...Test">
<constructor-arg index="0" type="java.lang.String" value="朱潔" />
<constructor-arg index="1" type="int" value="20"/>
<constructor-arg index="2" type="double" value="34.5" />
</bean>
2.3.3.4 分散配置
通過在ApplicationContext.xml檔案中配置context:property-placeholder 引入屬性檔案,有多個需要使用’,'号間隔.
步驟如下:
- 配置屬性檔案db.property
name=scott
drivername=oracle:jdbc:driver:OracleDirver
url=jdbc:oracle:thin:@127.0.0.1:1521:hsp
pwd=tiger
-
在ApplicationContext.xml檔案中引入db.properties檔案,兩種方式
第一種
第二種
<bean id="dbPropertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>xx/yy/db.properties</value>
<value>xx/yy/db2.properties</value>
</list>
</property>
</bean>
- 在ApplicationContext.xml檔案中配置bean,采用占位符$方式
<bean id="dbutil" class="com.hsp.dispatch.DBUtil">
<property name="name" value="${name}" />
<property name="drivername" value="${drivername}" />
<property name="url" value="${url}" />
<property name="pwd" value="${pwd}" />
</bean>
2.3.3.5 自動裝配
- 通過autowire屬性裝配
<bean id="foo" class="...Foo" autowire="autowire
type">
有四種自動裝配類型:
- byName尋找和屬性名相同的bean,若找不到,則裝不上。(屬性名和bean id名必須相同)
- byType:尋找和屬性類型相同的bean,找不到,裝不上,找到多個抛異常。
- constructor:查找和bean的構造參數一緻的一個或多個bean,若找不到或找到多個,抛異常。按照參數的類型裝配
- autodetect: (3)和(2)之間選一個方式。不确定性的處理與(3)和(2)一緻。
- defualt : 這個需要在
- no : 不自動裝配,這是autowrite的預設值。
老闆:不懂spring還來做項目?建議離職一、Spring架構二、裝配Bean default說明
需要在
- 如果在指定了default-atuowrite後,所有的bean的預設的autowire就是中指定的裝配方法;
- 如果沒有在指定defualt-autorwire,則預設是defualt-autorwire=”no”,所有的bean則預設不自動裝配,除非自己配置autowire
篇幅有限,暫時更新到這裡啦!下一篇盡快上傳~
看到這裡的小夥伴,如果你喜歡這篇文章的話,别忘了轉發、收藏、留言互動!
最近我新整理了一些Java資料,包含面經分享、模拟試題、和視訊幹貨,如果你需要的話,歡迎私信我!
如果對文章有任何問題,歡迎在留言區和我交流~
還有,關注我!關注我!關注我!