Ioc 控制反轉 -> 依賴 DI (依賴注入) + 容器container
Aop 切面編程 -> 依賴 proxy (動態代理)
以上兩個哥們兒就構成了 Spring 框架的核心功能
spring中的 IoC 控制反轉(Inversion of Control,英文縮寫為IoC)
Spring 中創建了一個容器, (ApplicationContext) 這個容器實質上是一個 map 它使用 key 名 管理著其中的物件
spring 啟動的時候, 根據組態檔中的配置, 把組態檔的所有物件都創建好后, 放入到容器中, 當使用的時候, 就從容器中把它拿出來就可以了 classpathApplicationContext.getBean(“物件鍵名”) 就可以得到這個物件了
spring的配置有兩種方式, 一種是XML檔案方式, 另一種是注解的方式,兩種方式各有優缺點
問題一 什么樣的類要讓容器來幫助我們自動創建呢?
我的理解, 工具類 service DaoImpl 這些類都是相當于, 我們寫好了, 只需要去呼叫就可以了, 這樣的類就適合把它們放到容器中, 我們隨時可以拿出來用, 這些別應該還有一個特點, 就是可以是一個單例.
同樣, domain 或者說 pojo 中的物體類, 就不適合放在容器中, 物體類在運行程序中,會根據引數的不同而賦值不同的物件, 它們也不可能會是一個單例
問題二 兩種配置方式, 是xml好, 還是注解方式好
我的理解, 兩種方式各有優缺點, 總結一下, 如果一個這個類不怎么變動的,就會用注解方式, 如果經常變動的就使用xml, 兩種組態檔是可以混用的
Spring ApplicationContext 介面實作類 ClassPathXmlApplicationContext
classPathXmlApplication 就是容器, 它的構造方法,接收一個引數, 就是 組態檔
Spring xml 組態檔
我們在 專案的 classpath 目錄下 新建一個 組態檔 applicationContext.xml
類的容器加載時, 會注入類的物件實體到容器中, 物件的屬性只有兩種情況, 一種是基本資料型別和字串, 另一種是參考資料型別
同時賦值的方法, 也分兩種方法來賦值, 一種是通過物件的 setter 方法來賦值, 一種是通過物件的多參構造方法來賦值
下面是其本資料型別的兩種賦值方法
<!-- <bean id="student" class="com.huang.domain.Student">-->
<!-- <property name="age" value="10"></property>-->
<!-- <property name="name" value="蒼井空"></property>-->
<!-- <property name="sex" value="女"></property>-->
<!-- </bean>-->
//上面注釋的是使用類的 setter 方法賦值的, 也就是說spring會呼叫上面的 setter 方去對物件屬性賦值
-----------------------------------------------------------------------------
<bean id="student" class="com.huang.domain.Student">
<constructor-arg name="age" value="20"></constructor-arg>
<constructor-arg name="name" value="明日香"></constructor-arg>
<constructor-arg name="sex" value="女"></constructor-arg>
</bean>
//上面的方法是使用物件的構造方法來賦值的, 也就是說物件必須有多個引數的構造方法
屬性中有參考資料類據的資料的賦值方法
對例子中的student我們可以設一個學校 class School


可以看到 student類中的屬性有一個是參考型別的School school , 此時如果要創建 student 物件,就必須要有 school物件
所以我們的 applicationContext.xml配置如下
<bean id="student" class="com.huang.domain.Student">
<property name="age" value="20"></property>
<property name="name" value="波多野結衣"></property>
<property name="sex" value="女"></property>
<property name="school" ref="myschool"></property>
</bean>
<bean id="myschool" class="com.huang.domain.School">
<property name="address" value="日本稻田省"></property>
<property name="name" value="稻田大學"></property>
</bean>
組態檔中, bean 是可以不分先后順序的,都可以加載, 在student 中的參考物件 使用了 ref 來為其賦值,同時 ref的值是指向的 要使用的 bean的 id
我們在指字class的時候,使用的class的 全類名, 但是 spring 也可以智能的 根據類的型別, 或者根據類的名稱來自動加載; 如下例, 我們可以在組態檔中這樣寫
自動裝配有以下幾種
no 默認的方式是不進行自動裝配,通過手工設定ref 屬性來進行裝配bean
byName 通過引數名 自動裝配,如果一個bean的name 和另外一個bean的 property 相同,就自動裝配,
byType 通過引數的資料型別自動自動裝配,如果一個bean的資料型別和另外一個bean的property屬性的資料型別兼容,就自動裝配
construct 構造方法中的引數通過byType的形式,自動裝配,
default 由上級標簽的default-autowire屬性確定,
我們主要用的有 byName 和 byType
<bean id="student" class="com.huang.domain.Student" autowire="byName">
<property name="age" value="20"></property>
<property name="name" value="波多野結衣"></property>
<property name="sex" value="女"></property>
<!-- <property name="school" ref="school111"></property> -->
</bean>
<bean id="school" class="com.huang.domain.School">
<property name="address" value="日本稻田省123"></property>
<property name="name" value="稻田大學123"></property>
</bean>
上面的配置中, 我們可以看到, bean id=student 中添加了屬性 autowire = byName 使用名稱自動裝配
在studnet類中 private School school 屬性名稱為 school 所以 自動裝配會找到 bean 中的 id 值也是 school 的bean 把這個 bean 自動賦值給 student.school
再來看一下 byType
<bean id="student" class="com.huang.domain.Student" autowire="byType">
<property name="age" value="20"></property>
<property name="name" value="波多野結衣"></property>
<property name="sex" value="女"></property>
<!-- <property name="school" ref="school111"></property> -->
</bean>
<bean id="school" class="com.huang.domain.School">
<property name="address" value="日本稻田省123"></property>
<property name="name" value="稻田大學123"></property>
</bean>
同樣的 bean student 中添加了一個 autowire的為 byType 的屬性
spring 加載的時候, 會根據 student 中的 private School school 根據 school的型別, School 和 bean中的物件, 是School的型別的 自動賦值,
所以, 如果bean 檔案中使用了 byType 的話, 其中如果有兩個或兩個以上的 School 的子類,或介面,或繼承類, 也就是 如果有多個 和 school同源的類, 是會 報錯的
Spring 注解方式的使用
@Component @Controller @Service @Repository
@Component在沒傳參的時候, 默認bean 的id 就是類名的首字母小寫
這四個注解的功能大體是一樣的, 都可以把類注入到容器中, 但是 @Controller @Service @Repository, 這三個又是各有個的特殊用途的
首先主組態檔的寫法, 因為是使用注解引入的,所以在主組態檔中不會有配置 bean 了, 換成了掃瞄 context:component-scan base-package
<?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">
<context:component-scan base-package="com.huang.dao.impl"></context:component-scan>
<context:component-scan base-package="com.huang.domain"></context:component-scan>
</beans>
上面的主檔案掃瞄了 com.huang.dao.impl 包 和 com.huang.domain 包
那么現在我樣在 ioc 容器中注入 student物件 和 school物件, 它的注解該怎么寫呢?
School類的寫法
package com.huang.domain;
import org.springframework.stereotype.Component;
@Component
public class School {
....
}
Student類的寫法
package com.huang.domain;
import org.springframework.stereotype.Component;
@Component
public class Student {
...
}
如果我們想注入的時候指定 生成的類的 key 值, 可以寫成 Component(“student1”) Component(“school1”)
上面的寫法只是注入了一個類的物件, 其中的屬性并沒有賦值
對屬性的賦值 屬性的賦值注解可以寫在屬性的名稱上, 也可以寫在屬性的setter方法上
分為簡單型別的屬性賦值和參考型別的屬性賦值
對簡單型別的屬性賦值,我們使用 @Value(“值”)
對參考型別的屬性賦值,我們使用 @Autowared @Resource 以及 @Autowared配合@Qualifter
先說簡單型別
package com.huang.domain;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class Student {
@Value("huangjunhui")
private String name;
@Value("20")
private Integer age;
@Value("男")
/*
@Value("天天打豆豆")
public void setName(String name) {
this.name = name;
}
*/
}
上面是使用value注解, 并且寫在屬性的屬性名上
也可以寫在setter 方法上
參考型別的注解方法
參考型別的注解也分為 byName 和 byType
其中 Spring 框架中提供了一種 注解叫 @Autowared
java的源代碼中提供了一種注解叫 @Resource
它們兩個可以實作同樣的功能
**這里說一下兩種注解的機制
@Autowared 這是Spring框架提供的一個注解, 它默認是以 byType的方式來注入物件的,如果想要以 byName的方式來注入物件, 就要把 @Autowared 和 @Qualifer(“名稱”)
@ resources 是java提供的一個注解方式, 它是全自動的注入物件的,
spring將name屬性決議為bean的名字,而type屬性則被決議成為bean的型別,所以如果使用name屬性,則使用by name的自動注入策略,如果使用type屬性則使用by type的自動注入策略,如果都沒有指定,則通過反射機制使用by name自動注入策略,
**
測驗下
public class Student {
@Value("huangjunhui")
private String name;
@Value("20")
private Integer age;
@Value("男")
private String sex;
@Autowired
private School school;
/*
@Autowired
public void setSchool(School school) {
this.school = school;
}
*/
}
可以看到 @Autowired 寫在屬性上和方法上都是可以的, 這是使用的是它默認的 byType的方法, spring會檢測到 要注入的屬性的型別是 School 型別的, 所以就在容器中找到相應的型別進行了注入
下面使用一下 @Autowired 和 @Qulifiter(“name”)
@Autowired
@Qualifier("school1")
public void setSchool(School school) {
this.school = school;
}
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component("school1")
public class School {
@Value("北大")
public String name;
@Value("北京海淀")
public String address;
}
我們把 class School 上的 Component(“school1”) 說明了, 當注入時 school1,就是注入的物件的名稱
同時, 我們在 Student 類的 getSchool 方法上 使用了 @Autowired 和 @Qualifter(“school1”) ,也就是使有byName 的方式, 指定了注入名稱為 school1的物件
使用 @resource 方式注入
@resource的執行方式
如果 @resource 沒有name屬性 ,則會使的屬性的名稱做為 name的值去查找 bean的id , 如果沒有找到,就使用 byType再操作一次,如果都沒有找到, 則報錯
如果 @resource 的name屬性有值, 則按 name 的值去查找 bean的id , 找到就賦值,找不到就報錯
當然, @Resource 也可以有 type屬性,不再多說了
以上就是 Spring的 IoC 的配置方式, 下一節要說 Spring 的 Aop
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/277640.html
標籤:java
