Spring 基礎學習筆記 上
爲什麼用spring?
這個就說到spring的兩大特性 - IOC 和 AOP 我們一個一個介紹。
IOC
Dependency Injection,依賴注入。瞭解設計模式中工廠模式的方法是一種採用了IOC思想的實現方式。這裏簡單介紹一下。
Sound方法中需要調用cat和dog的實例,一般的方式是在Sound中分別實例化對象。
這種方式 Sound 方法與Cat Dog緊密關聯,如果我們想降低這種關聯程度,可以添加一個Animal類,和一個InjectionHelper類,Sound中只知道自己調用了Animal的sound,但是並不清楚自己調用的是cat還是dog。而通過set方法將 cat 傳入Sound的這一過程,就是依賴注入。
AOP
AOP(Abstract Oriented Programming),面向切面編程。AOP是OOP的補充和完善,OOP通過封裝繼承多態建立一種從上到下的系統層次,但對於與系統業務邏輯無關,每一層次都涉及的功能卻無能爲力,例如日誌。這種分散到各處的被稱爲橫切cross-cutting。
切面(Aspect):
一個關注點的模塊化,這個關注點橫切多個對象。例如logging,caching,transaction
連接點(Joinpoint):
程序執行過程中明確的點,如方法的調用,特定的異常被拋出或屬性的獲取。
通知(Advice):
切面在特定連接點採取的行動。
切入點(Pointcut):
指定一個通知將被引發的一系列連接點的集合
。
引入(Introduction):
添加方法或字段到被通知的類。
織入(Weaving):
組裝切面來創建一個被通知對象。這可以在編譯時或加載時完成,也可以在運行時完成。
安裝
- 下載 jar 包:https://repo.spring.io/release/org/springframework/spring/
- 解壓並導入至 eclipse
選中項目右鍵
Add External Jars 進入Spring解壓目錄 spring-framework-5.1.3.RELEASE-dist\spring-framework-5.1.3.RELEASE\libs 選中所有
- apply
- src 下建立xml文件命名隨意,我這裏叫做SpringConfig.xml
- 把一下內容填寫到SpringConfig.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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd ">
</beans>
簡單理解Spring IOC
Spring xml 文件將object轉化爲bean標籤,id爲實例化對象的名稱,class是所指向的Java類。Java類的屬性通過標籤寫在對應的bean中。xml中所有bean標籤代表的Object 就這樣被Spring控制。Spring根據bean的id和class,創建實例,並通過set方法將bean標籤下所有配置,注入到新建的實例中。由於這些操作Object是被動方,Spring是主動方,這種實現方式又叫做控制反轉 。新建的這些實例,稱作bean,放在Bean Factory中,外部Object可以通過實例化beanFactory取得與SpringContainer的聯繫,通過getBean方法,獲取beanFactory 中的 bean。由於這些bean實際上就是類的實例,可以通過強轉換方式,轉化爲所需的類型。
簡單使用Spring
新建Cat
package hello;
public class Cat {
private String name;
//setters and getters
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void sound() {
System.out.println("Meow Meow Meow");
}
}
Sound方法
public class Sound {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("SpringConfig.xml");
Cat cat = (Cat)context.getBean("cat");
cat.sound();
}
}
修改XML文件,添加bean id爲cat,property標籤是爲普通的參數賦值,name指代cat類中的參數名
<bean id="cat" class="hello.Cat">
<property name="name" value="Jack" ></property>
</bean>
爲什麼使用ApplicationContext方式,而不用BeanFactory?
ApplicationContext 是功能更加強大的 BeanFactory 子接口,在BeanFactory 的基礎上 多了資源加載,事件觸發,消息處理的功能,所以一般來說可以用ApplicationContext,就不用BeanFactory。
構造器注入
如果需要注入構造器,使用constructor-arg標籤
// Cat.java
public class Cat {
private String name;
private String type;
private int id;
public Cat(String name, String type) {
this.name = name;
this.type = type;
}
public Cat(String name) {
this.name = name;
}
public Cat(int id) {
this.id=id;
}
public void sound() {
System.out.println("Meow Meow Meow");
}
}
// xml file
// 使用第一個構造器
<bean id="cat" class="hello.Cat">
<constructor-arg type="String" value="Jack" />
</bean>
// 使用第二個構造器
<bean id="cat" class="hello.Cat">
<constructor-arg type="int" value="Jack" />
</bean>
// 使用第三個構造器
<bean id="cat" class="hello.Cat">
<constructor-arg index="0" value="Jack" />
<constructor-arg index="1" value="British Shorthair" />
</bean>
對象注入
三種方式:
- xml 文件中使用 ref 指向 所需對象的bean id
// Cat.java
public class Cat {
private Card card;
public void sound() {
System.out.println(this.card.toString()+" sound: Meow Meow Meow");
}
// setters and getters
public Card getCard() {
return card;
}
public void setCard(Card card) {
this.card = card;
}
}
// Card.java
public class Card {
private String name;
private String type;
// setters and getters
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String toString() {
return "name: "+ this.name +" type: "+this.type;
}
}
// xml
<bean id="cat" class="hello.Cat">
<property name="card" ref="catCard"></property>
</bean>
<bean id="catCard" class="hello.Card">
<property name="name" value="Jack"></property>
<property name="type" value="cat"></property>
</bean>
- 通過 innerbean
<bean id="cat" class="hello.Cat">
<property name="card">
<bean id="catCard" class="hello.Card">
<property name="name" value="Jack"></property>
<property name="type" value="cat"></property>
</bean>
</property>
</bean>
- 通過 autowire=“byName” 僅當 參數屬性名稱和bean id相同時,本例子中,名稱都爲card。“byType” 僅當一種類型只有一個對象可用。
<bean id="cat" class="hello.Cat" autowire="byName"></bean>
<bean id="card" class="hello.Card">
<property name="name" value="Jack"></property>
<property name="type" value="SmallCat"></property>
</bean>
collection 注入
使用 list 標籤
// Cat.java
public class Cat {
List<Card> cardList;
public List getCardList() {
return cardList;
}
public void setCardList(List<Card> cardList) {
this.cardList = cardList;
}
public void sound() {
for(Card card:this.cardList) {
System.out.println(card.toString()+" sound: Meow Meow Meow");
}
}
}
// xml
<bean id="cat" class="hello.Cat">
<property name="cardList">
<list>
<ref bean="catCard1" />
<ref bean="catCard2"/>
<ref bean="catCard3"/>
</list>
</property>
</bean>
<bean id="catCard1" class="hello.Card">
<property name="name" value="Jack"></property>
<property name="type" value="SmallCat"></property>
</bean>
<bean id="catCard2" class="hello.Card">
<property name="name" value="Jack"></property>
<property name="type" value="MidCat"></property>
</bean>
<bean id="catCard3" class="hello.Card">
<property name="name" value="Jack"></property>
<property name="type" value="Bigcat"></property>
</bean>
Bean Scope
Singleton: 一個Spring Container一個bean,默認模式
Propotype:一個程式一個bean
Session:一個session一個bean
Request: 一個servlet Request一個bean
Global Session: 一個Http session一個bean
<bean id="card" class="hello.Card" scope="propotype"></bean>