第二章 IOC
文章目錄
- 第二章 IOC
- 2.1 IOC(Inversion of control)
- 2.1.1 IOC的第一個HelloWorld
- 2.1.2 在配置文件中為各種屬性賦值
- 1.null(重點)
- 2. 基本數據類型(重點)
- 3. 內部的bean或外部的bean(重點)
- 4. List,Map等(重點)
- 5. 使用util集合空間
- 6. 一個注意事項
- 7. 級聯屬性
- 8. 使用繼承實現配置信息的繼承
- 9. 指定bean是抽象的
- 2.1.3 bean的其他設置
- 1. 設置bean的依賴關系
- 2. 設置bean是否為單實例(重點)
- 3. 配置通過靜態工廠方法創建bean、實例工廠方法創建bean、FactoryBean(重點)
- 4. 實現FactoryBean的工廠(重點)
- 5. 創建帶有生命周期方法的bean
- 6. 后置處理器
- 6. 引用外部屬性文件(重點)
- 7. 基于xml的自動裝配(自定義類型)
- 8. SpEl測試
- 9. 使用注解
- 9.1 使用@Scope()注解
- 10. 使用context:include-filter和context:exclude-filter制定掃描規則
- 11. @Autowired注解的使用
- 12. 使用@Qualifier()注解
- 13. @Autowired,@Resource,@Inject
- 14. 使用Spring的單元測試
- 15. 測試泛型依賴注入
- 2.1.4 IOC總結
第二章 IOC
2.1 IOC(Inversion of control)
IOC是控制反轉,在第一章中我們已經做了介紹,IOC的關鍵就是向容器中注冊組件。
2.1.1 IOC的第一個HelloWorld
之前都是new對象,現在所有的對象都交給容器創建和管理,所以,我們需要知道如何向容器中注冊組件。
在IDEA中新建一個空的項目,空的項目創建完成后,在項目中新建一個maven包,在新建的maven包中的pom.xml配置文件中加入以下的依賴:
<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.1.10.RELEASE</version></dependency> </dependencies>我們只導入了一個springframework的依賴,其他的依賴會自動幫我們導入
更改后的pom.xml文件內容如下:
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.jxd</groupId><artifactId>helloworld</artifactId><version>1.0-SNAPSHOT</version><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.1.10.RELEASE</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version><scope>test</scope></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter</artifactId><version>RELEASE</version><scope>compile</scope></dependency></dependencies><build></build> </project>編寫一個Person實體類:
package beans;public class Person {private String name;private Integer age;public Person(String name, Integer age) {this.name = name;this.age = age;}public Person() {}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';} }在main目錄下新建一個resources目錄,在這個目錄中新建一個名為beans.xml的Spring配置文件,如下:
<?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"><!-- 向容器中注冊一個ID為person1的Person對象 --><bean id="person1" class="beans.Person"><!-- 設置person1的name屬性為張三 --><property name="name" value="張三"></property><!-- 設置person1的age屬性為12 --><property name="age" value="12"></property></bean></beans>注意:
下面編寫一個測試類,從容器中獲取注冊的id為person1的Person對象:
package com.jxd.test;import com.jxd.beans.Person; import org.junit.jupiter.api.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;public class Test1 {public static void main(String[] args) {ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");Person tom = (Person) ioc.getBean("person1");System.out.println(tom);}}運行結果:
Person{name='tom', age=12}整個包的目錄結構如下:
注意:
如果bean.xml不是在類路徑下,我們可以使用FileSystemXmlApplicationContext(“F://bean.xml”)
注意:Eclipse中增加注解可能會報錯,右鍵項目,選擇Java Compiler,在右邊的選項中找到Enable project specific settings,將其勾選,找到Compiler compliance setting后面的版本,將其調高到1.7。
2.1.2 在配置文件中為各種屬性賦值
在上面的例子中,我們使用配置文件的方法向IOC容器中注冊注冊了一個Person組件(對象)并為它的name、age屬性賦值。但是,name、age的屬性值都是基本的數據類型,然而在現實中,對象的屬性也有可能是對象類型、數組、Map等一些復雜的屬性;因此,我們還需要掌握為對象的各種復雜類型的屬性進行賦值。
下面就介紹了如何向容器中注冊的組件的各種屬性賦值。
1.null(重點)
<bean id="man1" class="beans.Man"><!-- String類型不賦值就是null,int默認是0 --><property name="name"><null/></property> </bean>2. 基本數據類型(重點)
<bean id="book1" class="beans.Book"><property name="price" value="12"/><property name="name" value="活著"/> </bean>3. 內部的bean或外部的bean(重點)
<bean id="man1" class="beans.Man"><property name="car"><!-- 相當于car = new Car(),它引用內部的bean。在當前bean之外不能被獲取到,只能內部使用--><bean class="beans.Car"><property name="carName" value="自行車"/><property name="price" value="350"/></bean></property> </bean><!-- 在外部創建一個id為motorbike的Car對象 --> <bean id="motorbike" class="beans.Car"><property name="carName" value="摩托車"/><property name="price" value="3000"/> </bean><bean id="man1" class="beans.Man"><!-- 使用ref屬性直接引用外部的car1 --><property name="car" ref="motorbike"></property> </bean>
4. List,Map等(重點)
<bean id="man2" class="beans.Man"><!-- 如何為List賦值 --><property name="booksList" ><list><bean class="beans.Book" p:name="西游記"/><ref bean="book1"/></list></property><!-- 為map賦值 --><property name="map"><!-- new map LinkedHashMap<>() --><map><!-- 一個entry就代表一個鍵值對 --><entry key="key01" value="張三"/><entry key="key02" value="14"/><entry key="key03" value-ref="book1"/><entry key="ley04"><bean class="beans.Car"><property name="carName" value="單車"/><property name="price" value="123"/></bean></entry></map></property><!-- 為Properties對象賦值 --><property name="properties"><props><prop key="userName">root</prop><prop key="password">123456</prop></props></property> </bean>5. 使用util集合空間
<!-- util名稱空間創建map類型的bean,方便別人引用--> <util:map id="myMap1"><entry key="key0" value="value0"/><entry key="key1" value="value1"/> </util:map> <bean id="man3" class="beans.Man"><property name="map" ref="myMap1"/> </bean>注意:
使用util名稱空間需要導入響應的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:util="http://www.springframework.org/schema/util"xmlns:p="http://www.springframework.org/schema/p"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/utilhttp://www.springframework.org/schema/util/spring-util-4.0.xsd">6. 一個注意事項
<!-- 注意:下面的標簽是賦值的列表是:[[], Man, 12, {}]--> <util:list id="list1"><list/><bean class="beans.Man"/><value>12</value><ref bean="myMap1"/> </util:list>7. 級聯屬性
級聯屬性也別稱作為屬性的屬性,比如:Man類有一個類型為Car的car屬性,而Car對象又有一些自己的屬性,這些屬性就被稱為級聯屬性。
<bean id="motorbike" class="beans.Car"><property name="carName" value="摩托車"/><property name="price" value="3000"/> </bean><!-- 級聯屬性(屬性的屬性)--> <bean id="man4" class="beans.Man"><property name="car" ref="motorbike"/><property name="car.price" value="1000000"/> </bean>8. 使用繼承實現配置信息的繼承
<!-- 通過繼承來實現bean配置信息的重用 --> <bean id="man5" class="beans.Man"><property name="age" value="23"/> </bean> <!-- parent: 指定bean的配置信息繼承于哪個bean --> <bean id="man6" class="beans.Man" parent="man5"><property name="name" value="小明"/> </bean>注意:這里的繼承和java中的繼承不同,這里的繼承只是繼承了bean的配置信息,而不代表某個bean是另一個bean的父類。
9. 指定bean是抽象的
<!-- 指定一個bean是抽象的,不能實例化(也就是不能從容器中獲取),只能被繼承 --> <bean id="man7" class="beans.Man" abstract="true"></bean>2.1.3 bean的其他設置
1. 設置bean的依賴關系
<!-- 默認bean是根據配置的順序來創建bean --> <!-- bean之間的依賴(只能改變創建的順序) --> <bean id="man1" class="beans.Man" depends-on="car1,book1"></bean> <bean id="car1" class="beans.Car"></bean> <bean id="book1" class="beans.Book"></bean>設置man1依賴于car1和book1后,就會先創建car1,在創建book1,然后才會創建man1。
2. 設置bean是否為單實例(重點)
<!-- bean的作用域,創建單實例和多實例的bean --> <!--prototype:多實例(常用)singleton:單實例,默認的(常用)request:在web環境下,同一次請求創建一個Bean實例(沒用)session:在web環境下,同一次會話創建一個Bean實例(沒用)--> <bean id="man2" class="beans.Man" scope="prototype"></bean>將bean設置為多實例后,每次從容器中獲取該對象都會新創建一個。
3. 配置通過靜態工廠方法創建bean、實例工廠方法創建bean、FactoryBean(重點)
bean的創建默認就是框架利用反射new出來的實例。
靜態工廠:工廠本身不用創建,也就是工廠類中獲取對象的方法是靜態的,可以直接通過靜態工廠名.方法名來獲取對象
實例工廠:工廠本身必須創建,創建后再使用這個工廠實例的方法來獲取對象
<!-- 配置通過實例工廠或靜態工廠來實例化bean --><!-- 使用靜態工廠 --> <!-- BookStaticFactory是我們自己創建的靜態工廠java類--> <bean id="book2" class="factory.BookStaticFactory"factory-method="getBook"><constructor-arg value="書名1"></constructor-arg> </bean><!-- 實例工廠 --> <!--1.先創建實例工廠bean--> <!-- BookFactory也是我們創建的實例工廠java類 --> <bean id="instanceBookFactory" class="factory.BookFactory"></bean> <!-- 2.再使用factory-bean指定是哪個靜態工廠bean,使用factory-method指定靜態工廠中的方法 --> <bean id="book3" class="factory.BookFactory" factory-bean="instanceBookFactory" factory-method="getBook"><!-- 3.再使用constructor-org 配置工廠方法中的輸入參數--><constructor-arg name="bookName" value="書名2"></constructor-arg> </bean>4. 實現FactoryBean的工廠(重點)
FactoryBean是Spring規定的一個接口,一個類只要是這個接口的實現類,Spring都認為這個一個工廠,且實現這個接口的工廠只會在需要的時候才創建對象。
package factory;import beans.Book; import org.springframework.beans.factory.FactoryBean;public class MyFactoryBeanImpl implements FactoryBean<Book> {/*** 工廠方法,在Spring的配置中注冊這個工廠bean就會自動調用* getObject()方法,也就是你注冊的是一個book,不是這個工廠的bean* @return 返回創建的對象*/@Overridepublic Book getObject() {// Book實體類請大家自己創建Book book = new Book();book.setName("java從入門到放棄");return book;}/*** 返回創建對象的類型* Spring會自動調用這個方法來確定我們創建對象的類型* @return 對象的類型*/@Overridepublic Class<?> getObjectType() {return Book.class;}/*** 判斷創建的對象是否是單例* @return 創建的對象是否是單例*/@Overridepublic boolean isSingleton() {return FactoryBean.super.isSingleton();} }將我們繼承了FactoryBean的工廠類注冊到容器中:
<!-- 因為MyFactoryImpl是繼承了FactoryBean,也就是Spring認識這個工廠,在注冊這個工廠的時候,Spring就自動幫你調用的getObject()方法了,于是注冊這個工廠就是注冊了一個這個工廠類返回的對象,在本例子中就是Book組件,并且Spring不會在Spring啟動的時候就創建對象,而是需要的時候才創建,且這與對象是否是單實例無關。--> <bean id="MyFactoryBeanImpl" class="factory.MyFactoryBeanImpl"></bean>大家可以自己測試一下從ioc容器獲取MyFactoryBeanImpl這個對象,看看它是不是一個name屬性為“java從入門到放棄”的Book對象。
5. 創建帶有生命周期方法的bean
bean的生命周期包括創建和銷毀,我們可以為bean自定義一些生命周期方法,Spring在創建或銷毀bean的時候就會調用我們指定的方法。
<bean id="book" class="Book" init-method="myInit" destroy-method="myDestroy"></bean>6. 后置處理器
Spring中有一個后置處理器接口BeanPostProcessor,可以在bean初始化前后調用相關的方法。
創建一個Book類:
public class Book {private String name;private Integer price;public void myInit(){System.out.println("生命周期方法myInit執行了!");}public void myDestroy(){System.out.println("生命周期方法myDestroy執行了!");}public Book() {}public Book(String name, Integer price) {this.name = name;this.price = price;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getPrice() {return price;}public void setPrice(Integer price) {this.price = price;} }創建一個實現了BeanPostProcessor這個接口的方法MyBeanPostProcessor:
import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor;public class MyBeanPostProcessor implements BeanPostProcessor {/*** 對象初始化之前調用* @param bean* @param beanName* @return* @throws BeansException*/@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("["+beanName+"]"+"調用初始化之前執行的方法了!");return bean;}/*** 對象初始化之后調用* @param bean* @param beanName* @return* @throws BeansException*/@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("["+beanName+"]"+"調用初始化之后執行的方法了!");return bean;} }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="book" class="Book" init-method="myInit" destroy-method="myDestroy"></bean><bean id="beanPostProcessor" class="MyBeanPostProcessor"></bean> </beans>編寫一個測試類:
import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;public class TestJ {@Testpublic void test1(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");Book book = (Book) applicationContext.getBean("book");System.out.println(book);} }運行結果:
[book]調用初始化之前執行的方法了! 生命周期方法myInit執行了! [book]調用初始化之后執行的方法了! Book@51e696596. 引用外部屬性文件(重點)
數據庫連接池作為一個單實例是最好的,一個項目一個連接池,而一個連接池中管理多個連接。可以讓Spring幫我們創建連接池對象,也就是注冊連接池組件。
因為我們創建的是maven包,所以也需要在pom.xml配置文件中引入c3p0所需的依賴:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>Spring-03-newTest</artifactId><version>1.0-SNAPSHOT</version><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.1.10.RELEASE</version></dependency><!-- https://mvnrepository.com/artifact/com.mchange/c3p0 --><dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.5.2</version></dependency><!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.16</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>RELEASE</version><scope>test</scope></dependency></dependencies><properties><maven.compiler.source>11</maven.compiler.source><maven.compiler.target>11</maven.compiler.target></properties></project>注意:同時需要mysql-connector-java和c3p0這兩個依賴
在applicationContext.xml文件中注冊連接池對象:
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="user" value="root"></property><property name="password" value="123456"></property><property name="driverClass" value="com.mysql.cj.jdbc.Driver"></property><property name="jdbcUrl" value="jdbc:mysql://localhost:3307/books?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC"></property></bean>編寫測試類從容器中獲取連接池對象并獲取一個數據庫連接:
import com.mchange.v2.c3p0.ComboPooledDataSource; import org.junit.Test; import org.springframework.context.support.ClassPathXmlApplicationContext;import java.sql.Connection; import java.sql.SQLException;public class TestJ {@Testpublic void test1() throws SQLException {ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");ComboPooledDataSource dataSource = (ComboPooledDataSource) applicationContext.getBean("dataSource");Connection connection = dataSource.getConnection();System.out.println(connection);}}我們習慣于將c3p0的配置抽取成一個配置文件,現在我們就將c3p0的配置文件抽取成一個c3p0Config.properties文件,我們在resources文件夾下創建一個名為c3p0Config.properties文件:
jdbc.user=root jdbc.password=123456 jdbc.driverClass=com.mysql.cj.jdbc.Driver jdbc.jdbcUrl=jdbc:mysql://localhost:3307/books?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC更改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"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.2.xsd" > <!-- <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">--> <!-- <property name="user" value="root"></property>--> <!-- <property name="password" value="123456"></property>--> <!-- <property name="driverClass" value="com.mysql.cj.jdbc.Driver"></property>--> <!-- <property name="jdbcUrl" value="jdbc:mysql://localhost:3307/books?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC"></property>--> <!-- </bean>--><!-- 引用外部配置文件 --><!--1. 需要引入context名稱空間 --><!--2. 使用context:property-placeholder的location屬性引入配置文件路徑 --><context:property-placeholder location="classpath:c3p0Config.properties"></context:property-placeholder><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="user" value="${jdbc.user}"></property><property name="password" value="${jdbc.password}"></property><property name="driverClass" value="${jdbc.driverClass}"></property><property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property></bean></beans>再次測試,我們發現同樣也成功了!
注意:由于username等其他單詞是spring中的個關鍵字,為了避免沖突,所以上面的properties配置文件中的字段都帶了jdbc.這個前綴
7. 基于xml的自動裝配(自定義類型)
如果自定義類型的bean的屬性是bean,且這個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"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="car" class="Car"><property name="carName" value="自行車"></property><property name="price" value="123"></property></bean><!-- 原來為bean的屬性對象賦值 --><bean id="man1" class="Man"><property name="car" ref="car"></property></bean><!-- 自動轉配,也就是創建對象時就為其屬性對象賦值 --><!-- autowire:default/no:不自動裝配byName:根據屬性名來尋找ID,來自動裝配,類似于ioc.getBean(id:"car"),如果找不到就裝配為nullbyType:通過類型來裝配,相當于ioc.getBean(class:"Car.class"),如果有多個,就會報錯,如果沒有找到,就裝配nullconstructor:按照構造器來裝配1.先按照有參構造器參數類型在ioc中尋找對象,如果有,就裝配,沒有,就直接裝配為null2.如果按照類型找到了多個,參數名作為id繼續匹配,找到就轉配,找不到,就裝配為null3.不會報錯--><bean id="man2" class="Man" autowire="byName"></bean> </beans>8. SpEl測試
SpEl是Spring Expression language的縮寫,Spring的表達式語言,支持運行時查詢并且可以操作對象。
基本語法
SpEL使用#{}作為定界符,所有在#{}中的字符串都可以認為是SpEl表達式
使用字面量
- 整數:<property name="count" value="#{12}"/>
- 小數:<property name="weight" value="#{23.32}"/>
- 科學計數法:<property name="count" value="#{12e3}"/>
- 字符串:<property name="name" value="#{'Tom'}"/>或<property name="name" value='#{"Tom"}'/>
- boolean值:<property name="married" value="false"/>
9. 使用注解
通過給bean添加一些注解就可以快速的將bean注冊到容器中。
@Controller:控制器,推薦給控制器層(servlet)加這個
@Service:業務邏輯,推薦給業務邏輯層加這個
@Repository:給持久化層(數據庫層,dao層)的組件加這個
@Componet:給不屬于以上幾個的添加
使用注解的步驟:
-
根據組件的類型,給要掃描的組件標上對應的注解
-
告訴Spring,自動掃描加了注解的組件,也就是配置掃描路徑,依賴context名稱空間
依賴aop包
-
加了注解的類的id默認是類名首字母小寫,使用注解加入到容器中的組件和通過配置加入到容器中的組件的行為和屬性都是一樣的
通過@Service這個注解,我們就將BookService這個組件注冊到了容器中;同時,我們也可以在注解后加上括號,在括號中寫入自定義的ID名來修改這個組件的ID名。
注意:使用注解來注冊的組件的ID名默認為將類名第一個字母小寫后的字符串,不要因為忘了這個導致 No bean named ‘XXXXX’
9.1 使用@Scope()注解
使用注解注冊的組件默認是單實例的,可以通過@Scope()注解來更改組件是否為單實例:
@Scope(value=“prototype”) 設置為多實例
@Scope(value=“singleton”) 設置為單實例
10. 使用context:include-filter和context:exclude-filter制定掃描規則
<?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 http://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.jxd"><!-- 掃描時排除的組件 --><!-- type="annotation"用于指定排除規則,標注了指定注解的組件不要expression: 注解的全類名type="assignable": 指定排除某個具體的類,按照類排除expression: 類的全類名--><context:exclude-filter type="assignable" expression="com.jxd.service.BookService"/></context:component-scan><!-- 先禁用原來的掃描方式(一定要禁用才有用!) --><context:component-scan base-package="com.jxd" use-default-filters="false"><!-- 只掃描哪些組件,默認是全部都掃描 --><!--type和expression的用法和exclude一樣--><context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/></context:component-scan></beans>11. @Autowired注解的使用
使用@Autowired注解可以讓容器將我們依賴的對象自動注入:
package com.jxd.service;import com.jxd.dao.BookDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service;@Service("bookService") public class BookService {@Autowiredprivate BookDao bookDao;public void saveBook(){System.out.println("正在調用BookDao的saveToDB方法");bookDao.saveToDB();} }使用@Autowired(required=false)可以指定如果找不到就裝配null。
常見的自動注入失敗原因:
@Autowired自動裝配的步驟:
- 第一步:按照類型再容器中找到對應的組件,
- 找到一個:裝配
- 未找到:異常
- 找到多個:
- 按照變量名作為Id繼續匹配
- 匹配上:裝配
- 沒有匹配上:異常
- 按照變量名作為Id繼續匹配
在方法上使用@Autowired注解:
如果在一個方法上使用了@Autowired注解,這個方法會在該bean創建的時候自動運行,且這個方法的每一個參數都會自動注入
12. 使用@Qualifier()注解
@Qualified()注解可以指定自動裝配時采用@Qualified("ID名")指定的ID來查找,如果通過@Qualified注解指定的ID來查找還是未找到,就會產生異常。
在方法的形參位置使用@Qualifier注解:
指定這個形參自動注入依據的ID名
13. @Autowired,@Resource,@Inject
它們都是自動裝配的注解,但是,@Autowired的功能是最強大的。
- @Autowired:最強大,Spring自己的注解
- @Resource:j2ee的標準,擴展性更強
- @Inject:是JSR330 (Dependency Injection for Java)中的規范
14. 使用Spring的單元測試
提示:需要依賴Spring的單元測試的jar包
例子:
package com.jxd.test;import com.jxd.service.BookService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;@ContextConfiguration(locations = "classpath:applicationConfig.xml") @RunWith(SpringJUnit4ClassRunner.class) public class TestJ1 {@AutowiredBookService bookService;@Testpublic void test1(){bookService.saveBook();} }@ContextConfiguration(location=“ ”):用來指定Spring的配置文件的位置
@RunWith( ):指定用那種驅動進行單元測試,默認是junit
15. 測試泛型依賴注入
泛型依賴注入,注入一個組件的時候,它的泛型也是參考標準。
Spring中可以使用帶泛型的父類類型來確定子類的類型。
2.1.4 IOC總結
IOC(Inversion of control)是一個容器,它可以幫我們管理注冊到容器中的組件(類)。容器啟動,會創建所有的單實例bean,autowired自動裝配的時候,是從容器中找到符合要求的bean,ioc.getBean(“ ”)也是從容器中找到指定的bean。這個容器其實是一個map,這個map保存了所有創建好的bean,并提供相應的功能。
感謝你的閱讀!
總結
- 上一篇: 为什么fm1支持DDR3内存条?揭秘性能
- 下一篇: 对爬虫爬取到的数据进行存储