spring筆記

  1. IoC 的概念和作用

1.1程序的耦合和解耦

  1. 什麼是程序的耦合

是對模塊間關聯程度的度量。模塊間聯繫越多,其耦合性越強.

  1. 什麼是內聚

內聚標誌一個模塊內各個元素彼此結合的緊密程度,一個好的內聚模塊應當恰好做一件事。

  1. 解耦

我們在開發中,有些依賴關係是必須的,有些依賴關係可以通過優化代碼來解除的。

1.2 控制反轉

1.什麼是控制反轉IOC?

把創建對象的權利交給框架。它包括依賴注入DI和依賴查找DL。意思就是之前我們需要對象的時候,自己new。現在我們把對象的創建權,交給spring工廠,我們需要對象的時候,從工廠中去拿。

作用:削減計算機程序的耦合(解除我們代碼中的依賴關係)

 

  1. 使用 spring 的 IOC 解決程序耦合

2.1 spring基於xml的配置

2.1.1spring 中工廠的類結構圖

2.1.1.1 BeanFactory 和 ApplicationContext 的區別

BeanFactory 纔是 Spring 容器中的頂層接口。

ApplicationContext 是它的子接口。

BeanFactory 和 ApplicationContext 的區別:

創建對象的時間點不一樣。

ApplicationContext:只要一讀取配置文件,默認情況下就會創建對象。

BeanFactory:什麼使用什麼時候創建對象。

2.1.1.2 ApplicationContext 接口的實現類

ClassPathXmlApplicationContext:

它是從類的根路徑下加載配置文件 推薦使用這種

FileSystemXmlApplicationContext:

它是從磁盤路徑上加載配置文件,配置文件可以在磁盤的任意位置。

AnnotationConfigApplicationContext:

當我們使用註解配置容器對象時,需要使用此類來創建 spring 容器。它用來讀取註解。

2.1.2 IOC 中 bean 標籤和管理對象細節

2.1.2.1 bean 標籤(把對象交給spring容器管理)

作用:

用於配置對象讓 spring 來創建的。並且存入 ioc 容器之中

默認情況下它調用的是類中的無參構造函數。如果沒有無參構造函數則不能創建成功。

屬性:

id:給對象在容器中提供一個唯一標識。用於獲取對象。

class:指定類的全限定類名。用於反射創建對象。默認情況下調用無參構造函數。

scope:指定對象的作用範圍。

* singleton :默認值,單例的.

* prototype :多例的.

2.1.2.2 bean 的作用範圍和生命週期

單例對象:scope="singleton"

一個應用只有一個對象的實例。它的作用範圍就是整個引用。

生命週期:

對象出生:當應用加載,創建容器時,對象就被創建了。

對象活着:只要容器在,對象一直活着。

對象死亡:當應用卸載,銷燬容器時,對象就被銷燬了。

多例對象:scope="prototype"

每次訪問對象時,都會重新創建對象實例。

生命週期:

對象出生:當使用對象時,創建新的對象實例。

對象活着:只要對象在使用中,就一直活着。

對象死亡:當對象長時間不用時,被 java 的垃圾回收器回收了。

2.1.2.3 實例化 Bean 的三種方式

第一種方式:使用默認無參構造函數

<!--在默認情況下:

它會根據默認無參構造函數來創建類對象。如果 bean 中沒有默認無參構造函數,將會創建失敗。-->

<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"/>

2.1.3 spring 的依賴注入

2.1.3.1 依賴注入的概念

依賴注入:Dependency Injection。它是 spring 框架核心 ioc 的具體實現。

我們的程序在編寫時,通過控制反轉,把對象的創建交給了 spring,但是代碼中不可能出現沒有依賴的情況。

ioc 解耦只是降低他們的依賴關係,但不會消除。例如:我們的業務層仍會調用持久層的方法。

那這種業務層和持久層的依賴關係,在使用 spring 之後,就讓 spring 來維護了。

簡單的說,就是坐等框架把持久層對象傳入業務層,而不用我們自己去獲取。

2.1.3.2 構造函數注入

顧名思義,就是使用類中的構造函數,給成員變量賦值。注意,賦值的操作不是我們自己做的,而是通過配置

的方式,讓 spring 框架來爲我們注入。具體代碼如下:

/**

*/

public class AccountServiceImpl implements IAccountService {

private String name;

private Integer age;

private Date birthday;

public AccountServiceImpl(String name, Integer age, Date birthday) {

this.name = name;

this.age = age;

this.birthday = birthday;

}

@Override

public void saveAccount() {

System.out.println(name+","+age+","+birthday);

}

}

<!-- 使用構造函數的方式,給 service 中的屬性傳值

要求:

類中需要提供一個對應參數列表的構造函數。

涉及的標籤:

constructor-arg

屬性:

index:指定參數在構造函數參數列表的索引位置

type:指定參數在構造函數中的數據類型

name:指定參數在構造函數中的名稱 用這個找給誰賦值

=======上面三個都是找給誰賦值,下面兩個指的是賦什麼值的

value:它能賦的值是基本數據類型和 String 類型

ref:它能賦的值是其他 bean 類型,也就是說,必須得是在配置文件中配置過的 bean

<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">

<constructor-arg name="name" value="張三"></constructor-arg>

<constructor-arg name="age" value="18"></constructor-arg>

<constructor-arg name="birthday" ref="now"></constructor-arg>

</bean>

<bean id="now" class="java.util.Date"></bean>

2.1.3.3 set 方法注入

顧名思義,就是在類中提供需要注入成員的 set 方法。具體代碼如下:

/** */

public class AccountServiceImpl implements IAccountService {

private String name;

private Integer age;

private Date birthday;

public void setName(String name) {

this.name = name;

}

public void setAge(Integer age) {

this.age = age;

}

public void setBirthday(Date birthday) {

this.birthday = birthday;

}

@Override

public void saveAccount() {

System.out.println(name+","+age+","+birthday);

}

}

<!-- 通過配置文件給 bean 中的屬性傳值:使用 set 方法的方式

涉及的標籤:

property屬性:

name:找的是類中 set 方法後面的部分

ref:給屬性賦值是其他 bean 類型的

value:給屬性賦值是基本數據類型和 string 類型的

實際開發中,此種方式用的較多。

-->

<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">

<property name="name" value="test"></property>

<property name="age" value="21"></property>

<property name="birthday" ref="now"></property>

</bean>

<bean id="now" class="java.util.Date"></bean>

2.2 spring基於基於註解的IOC 配置

2.2.1明確:寫在最前

註解配置和 xml 配置要實現的功能都是一樣的,都是要降低程序間的耦合。只是配置的形式不一樣。

關於實際的開發中到底使用xml還是註解,每家公司有着不同的使用習慣。所以這兩種配置方式我們都需要掌握

Spring常用註解開發原則 自己寫的類用註解,框架的類用配置文件。

<!-- 告知 spring 創建容器時要掃描的包 -->

<context:component-scan base-package="com.itheima"></context:component-scan>

2.2.2常用註解

2.2.2.1用於創建對象的相當於:<bean id="" class="">

在需要創建對象的類上加上對應IOC註解

@Component組件註解,該註解放在哪個類上,就表示把哪個類交給spring容器管理,value:指定 bean 的 id。如果不指定 value 屬性,默認 bean 的 id 是當前類的類名。首字母小寫。

下面三個註解都是組件註解的延伸註解,是spring對三層開發中每一層對象註解的一個規範。

@Controller 使用於web層

@Service使用於service層

@Repository使用於dao層

2.2.2.2用於注入數據的相當於:<property name="" ref=""> <property name="" value="">

ioc註解的屬性對象必須存在於spring的容器中

@Autowired:自動按照類型注入。默認會去spring容器中按照類型尋找所需要注入的對象,如果找到一個唯一類型,就注入成功。如果找到不是唯一類型,

使用要注入的對象變量名稱作爲 bean 的 id,在 spring 容器查找,找到了也可以注入成功。找不到就報錯.

如果該註解裏面配置上了required=false,那麼在找不到類型也找不到名字的時候,會返回null值,不會報錯。但是如果不配置,就報錯。

@Resource:該註解是直接按照名稱注入。名稱找不到再按照類型注入。如果都找不到,就報錯。屬性:name:指定 bean 的 id。

@Value:注入基本數據類型和 String 類型數據的.屬性:value:用於指定值

2.2.2.3用於改變作用範圍的:相當於:<bean id="" class="" scope="">

 @Scope註解:改變對象作用域的,屬性:value:指定範圍的值。取值:singleton prototype

單例對象生命週期:容器創建,對象創建,容器在,對象在,容器銷燬,對象也銷燬。

多例對象生命週期:真正使用的時候,對象創建,一直存在,由java垃圾回收器回收。

2.2.3 Spring 整合 Junit

(1)@RunWith 註解替換原有運行器

@RunWith(SpringJUnit4ClassRunner.class)

(2)使用@ContextConfiguration 指定 spring 配置文件的位置

@ContextConfiguration(locations= {"classpath:bean.xml"})

@ContextConfiguration 註解:

locations 屬性:用於指定配置文件的位置。如果是類路徑下,需要用 classpath:表明

classes 屬性:用於指定註解的類。當不使用 xml 配置時,需要用此屬性指定註解類的位置。

  1. AOP

3.1 AOP的相關概念

3.1.1 什麼是AOP

Aop就是面向切面編程。我們可以在不修改源碼的基礎之上,對一個層面的代碼進行增強。AOP編程是一個思想,spring的aop底層是使用了jdk動態代理或cglib動態代理實現的。

【動態代理學會一種,另一種也就會了,只是換了下類而已】

我理AOP就是假設A有三個方法,a,b,c

現在要對A進行增強,就是給他增加新的方法,不在A的代碼中添加,而是新建一個動態代理類,在他裏邊給A加一個新的方法d

3.1.2 AOP 的作用及優勢

作用:

在程序運行期間,不修改源碼對已有方法進行增強。

優勢:

減少重複代碼

提高開發效率

維護方便

3.1.3 AOP 的實現方式

使用動態代理技術

3.2動態代理

3.2.1 Jdk動態代理

Jdk動態代理必須是對接口或者是接口的實現類。

 

創建一個java工程,確保有jdk的包。

編寫一個需要被增強的類,該類實現了一個接口

創建一個工廠,生產代理對象

工廠中必須提供一個需要被增強的對象的實例或者接口本身

獲取代理對象的方法

3.2.2 Cglib動態代理

Cglib是對類的增強的。

導入cglib的jar包

直接導入spring核心包,裏面整合了有cglib的包。

編寫一個需要被增強的類,該類暫時不實現接口

編寫一個工廠,來生成代理對象

必須提供一個被代理對象的實例

提供一個生成代理對象的方法

測試類

3.2 spring中的aop

3.2.1Spring的AOP開發步驟

我們學習 spring 的 aop,就是通過配置的方式,實現上一章節的功能。

3.2.2 AOP相關術語

Pointcut連接點:被增強類中所有的方法都是連接點。

Joinpoint切入點:被增強的方法是切入點

Advice(通知/增強):就是增強類

Target(目標對象):被代理對象

Proxy(代理):最終代理對

Aspect(切面):切面就是通知和切入點的組合。

Weaving(織入):把增強類中的方法增強到目標的過程。

可見,所謂面向切面編程,說白了,就是要編寫一通知,把通知中的方法織入到切入點上。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章