Spring(基於註解的IOC配置)
一、利用 spring的 IoC(xml配置)來實現賬戶的 CRUD[掌握]
步驟一:建立工程並匯入依賴(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.0http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.itcast.spring</groupId>
<artifactId>spring_day02</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--springIOC相關-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
<!--springjdbc相關-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.32</version>
</dependency>
<!-- 連線池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.9</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
步驟二:建立資料庫和實體類
建立資料庫:
create table account(
id int primary key auto_increment,
name varchar(40),
money float
)character set utf8 collate utf8_general_ci;
insert into account(name,money) values('aaa',1000);
insert into account(name,money) values('bbb',1000);
insert into account(name,money) values('ccc',1000);
自己編寫實體類Account(私有,有getter和setter方法、重寫tostring)
步驟三:建立service介面和實現類
介面:
實現類:
步驟四:建立dao介面和實現類
介面:
實現類:
步驟五:建立配置檔案
步驟六:建立測試用例
步驟七:載入外部資原始檔
在類的根路徑下新增jdbc.properties:
內容如下:
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.username=root
jdbc.password=root
修改applicationContext.xml:
二、 基於註解的IOC配置[掌握]
1、 明確:寫在最前
註解配置和xml配置要實現的功能都是一樣的,都是要降低程式間的耦合。
2、環境搭建
2.1 建立maven工程並匯入座標
複製spring_day02然後重新命名為spring_day02_02即可:重新命名工程、重新命名pom.xml中的artifactId,刪除其他檔案只留下src和pom.xml,然後在idea中開啟即可。
2.2 使用註解裝配bean
@Component
作用: 在類上使用該註解,把資源讓spring來管理。相當於在xml中配置一個bean。( <bean id="" class="">)
屬性: value:指定bean的id。如果不指定value屬性,預設bean的id是當前類的類名。首字母小寫。
@Controller @Service @Repository
他們三個註解都是針對@Component的衍生註解,他們的作用及屬性都是一模一樣的。
他們只不過是提供了更加明確的語義化。
@Controller:一般用於表現層(web)的註解。
@Service:一般用於業務層(service)的註解。
@Repository:一般用於持久層(dao)的註解。
細節:如果註解中有且只有一個屬性要賦值時,且名稱是value,value在賦值時可以不寫。
步驟一:建立配置檔案
先配置註解掃描的包,如圖:紅色
步驟二:使用註解裝配bean
裝配service:
/**
* @Component註解:相當於配置了<bean>標籤
* value = "accountService":相當於配置了bean標籤的id屬性,單獨配置value時,可以省略value屬性名稱。
*/
裝配dao:
步驟三:進行測試
建立demo的測試方法分別獲取service的實現類和dao的實現類,發現@Component的註解已經生效。
但是如果使用其他的crud的測試方法,會報空指標異常。
原因:AccountDaoImpl並沒有被注入到AccountServiceImpl中。(相當於xml檔案中紅色部分沒有配置)
<bean id="accountService" class="cn.itcast.service.impl.AccountServiceImpl"> //@Component
<property name="accountDao" ref="accountDao"></property> //@Autowired
</bean>
2.3 用於注入資料的
@Autowired
作用:
自動按照型別注入。當使用註解注入屬性時,set方法可以省略。它只能注入其他bean型別。當有多個型別匹配時,使用要注入的物件的變數名稱作為bean的id,在spring容器查詢,找到了也可以注入成功。找不到就報錯。
service實現類
dao實現類:
@Qualifier
作用: (1)在自動按照型別注入的基礎之上,再按照Bean的id注入。它在給欄位注入時不能獨立使用,必須和@Autowire一起使用;(2)但是給方法引數注入時,可以獨立使用。
屬性: value:指定bean的id。
新增第二個dao實現類:
內容如下:複製AccountDaoImpl後重命名為AccountDaoImpl2即可
指定注入AccountDaoImpl2:
@Resource
作用: 直接按照Bean的id注入。它也只能注入其他bean型別。(相當於@Autowired+@Qualifier)
屬性: name:指定bean的id。
@Value
作用: 注入基本資料型別和String型別資料的
屬性: value:用於指定值
註解裝配bean和註解注入的使用方式(重點)
1、自己編寫的類,都可以使用註解裝配到容器中。
2、沒有辦法使用註解裝配的第三方的類,可以使用<bean>標籤裝配。
3、只要是在spring容器中的bean,都可以使用註解注入。
2.4 用於改變作用範圍的
相當於:<bean id="" class="" scope="">
@Scope
作用:指定bean的作用範圍。
屬性:value:指定範圍的值。取值:singleton prototype request session globalsession
2.5 和生命週期相關的:(瞭解)
相當於:<bean id="" class="" init-method="" destroy-method="" />
@PostConstruct
作用:用於指定初始化方法。
@PreDestroy作用:
作用:用於指定銷燬方法。
2.6 關於Spring註解和XML的選擇問題
註解的優勢:
配置簡單,維護方便(我們找到類,就相當於找到了對應的配置)。
XML的優勢:
修改時,不用改原始碼。
Spring管理Bean方式的比較:
三、案例:使用註解IOC改造作業[掌握]
步驟一:建立maven工程並匯入座標
複製spring_day02_02然後重新命名為spring_day02_03即可:重新命名工程、重新命名pom.xml中的artifactId,刪除其他檔案,只留下src和pom.xml後,通過idea開啟即可。
步驟二:建立web層
建立一個AccountController,假設屬於web層,只需測試新增方法即可。
步驟三:建立service介面和實現類
實現類:修改注入方式即可。
介面:和之前的一樣
實現類:
步驟四:建立dao介面和實現類
實現類:修改注入方式即可。
介面:和之前的一樣
實現類:
步驟六:建立配置檔案
步驟七:建立測試用例
建立web層的測試用例:
2、待改造的問題
我們發現,之所以我們現在離不開xml配置檔案,是因為我們有一句很關鍵的配置:
<!-- 告知spring框架在,讀取配置檔案,建立容器時,掃描註解,依據註解建立物件,並存入容器中 -->
<context:component-scan base-package="cn.itcast"></context:component-scan>
如果他要也能用註解配置,那麼我們就離脫離xml檔案又進了一步。
另外,資料來源和QueryRunner的配置也需要靠註解來實現。
3、新註解說明
@Configuration
作用:
用於指定當前類是一個spring配置類,當建立容器時會從該類上載入註解。(相當於applicationContext.xml檔案)
獲取容器時需要使用AnnotationApplicationContext(有@Configuration註解的類.class)。
示例程式碼:
/**
* spring的配置類,相當於applicationContext.xml檔案
*/
@Configuration
public class SpringConfiguration {
}
注意:
我們已經把配置檔案用類來代替了,但是如何配置建立容器時要掃描的包呢?
請看下一個註解
@ComponentScan
作用:
用於指定spring在初始化容器時要掃描的包。作用和在spring的xml配置檔案中的:
<context:component-scan base-package="cn.itcast"></context:component-scan>
屬性:
Value(單獨使用可省略):用於指定要掃描的包。和標籤中的base-Package屬性作用一樣。
示例程式碼:
@Configuration //spring的配置類,相當於applicationContext.xml檔案
@ComponentScan("cn.itcast") //配置掃描的包
public class SpringConfiguration {
}
注意:
我們已經配置好了要掃描的包,但是資料來源和QueryRuner物件如何從配置檔案中移除呢?
請看下一個註解。
@Bean
作用: 該註解只能寫在方法上,將方法的返回值作為一個bean,並且放入spring容器。
屬性: name:給當前@Bean註解方法建立的物件指定一個名稱(即bean的id)。
注意:
我們已經把資料來源和QueryRunner從配置檔案中移除了,此時可以刪除bean.xml了。
但是由於沒有了配置檔案,建立資料來源的配置又都寫死在類中了。如何把它們配置出來呢?
請看下一個註解。
@PropertySource
作用:
用於載入.properties檔案中的配置(載入外部資原始檔)。例如我們配置資料來源時,可以把連線資料庫的資訊寫到properties配置檔案中,就可以使用此註解指定properties配置檔案的位置。
屬性:
value[]:用於指定properties檔案位置。如果是在類路徑下,需要寫上classpath:
@Import
作用:
用於匯入其他配置類,在引入其他配置類時,其他類上可以不用再寫@Configuration註解。當然,寫上也沒問題。
屬性:
value[]:用於指定其他配置類的位元組碼。
示例程式碼:
@Configuration //宣告這是一個配置類
@ComponentScan("cn.itcast") //配置掃描包
@Import(value = { JdbcConfig.class }) //匯入JdbcConfig配置類(首字母大寫)
public class SpringConfiguration {
}
@Configuration//寫不寫都行
@PropertySource(value = { "classpath:jdbc.properties" }) //載入外部資源
public class JdbcConfig {
}
注意:
我們已經把要配置的都配置好了,但是新的問題產生了,由於沒有配置檔案了,如何獲取容器呢?
請看下一小節。
通過註解獲取容器
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
4、純註解案例
步驟一:環境搭建
複製之前的工程,重新命名工程名稱,重新命名pom.xml中的artifactId, 刪除其他檔案,只留下src和pom.xml後,通過idea開啟即可。
步驟二:建立配置類
如果在一個配置類中需要裝配很多的bean到容器中,那麼顯然將所有的bean放在一個配置類是非常不利於管理的,因此我們可以選擇將bean分拆到其他類中單獨管理,最後再通過配置類來引入其他類即可。
在resources類的根目錄下建立properties資原始檔:
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/heima25
jdbc.username=root
jdbc.password=root
springConfiguration:
步驟三:測試
四、 Spring整合junit
1、 測試類中的問題和解決思路
問題:
在測試類中,每個測試方法都有以下兩行程式碼:
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
AccountController accountController = (AccountController) ac.getBean("accountController");
這兩行程式碼的作用是獲取容器,如果不寫的話,直接會提示空指標異常。所以又不能輕易刪掉。
解決思路分析
針對上述問題,我們需要的是程式能自動幫我們建立容器。一旦程式能自動為我們建立spring容器,我們就無須手動建立了,問題也就解決了。
我們都使用過junit,但是junit都無法知曉我們是否使用了spring框架,更不用說幫我們建立spring容器了。不過好在,junit給我們暴露了一個註解,可以讓我們替換掉它的執行器。
這時,我們需要依靠spring框架,因為它提供了一個執行器,可以讀取配置檔案(或註解)來建立容器。我們只需要告訴它配置檔案在哪就行了。
2、 涉及的註解
@RunWith
作用: 替換掉junit的執行器,換成一個可以初始化spring容器的執行器。
屬性: value:單獨配置時,value屬性名稱可以省略,配置SpringJUnit4ClassRunner.class來代替原來junit的執行器
@ContextConfiguration
作用: 載入配置類或者xml配置檔案
屬性:
value[]:用來指定xml配置檔案的路徑 location
class[]: 用來指定配置類 classes
3、 Xml的配置步驟
步驟一:環境搭建
複製之前的spring_day02_03(含xml配置檔案)工程重新命名後修改pom.xml中的artifactId,然後刪除其他檔案,只留下src和pom.xml後,通過idea開啟即可。
步驟二:匯入spring-test的座標
此處需要注意的是,spring5及以上版本要求junit的版本必須是4.12及以上,否則用不了。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
步驟三:測試
4、 純註解的配置步驟(配置類)
步驟一:環境搭建
複製spring_day02_04(含配置類)重新命名後修改pom.xml中的artifactId,然後刪除其他檔案,只留下src和pom.xml後,通過idea開啟即可。
步驟二:匯入spring-test的座標
此處需要注意的是,spring5及以上版本要求junit的版本必須是4.12及以上,否則用不了。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
步驟三:測試
-
註解總結
-
用於裝配Bean的註解
-
@Component(value=”xxx”):
一般用於將三層以為的bean裝配到容器中,value可以省略,value的屬性值作為bean的id
@Component的三個衍生註解:
@Controller(value=”xxx”):
一般用於將web層裝配到容器中,使用方法和@Component(value=”xxx”)一摸一樣
@Service(value=”xxx”):
一般用於將web層裝配到容器中,使用方法和@Component(value=”xxx”)一摸一樣
@Repository(value=”xxx”):
一般用於將web層裝配到容器中,使用方法和@Component(value=”xxx”)一摸一樣
-
用於屬性注入的註解
@Autowired:
只能按照bean型別注入,如果有多個型別匹配,預設將屬性名稱作為id去容器中查詢。
@Qualifier:
一般和@Autowired配合使用,用來注入指定id的bean,做方法的引數中可以獨立使用
@Resource:
用來注入指定id的bean型別,相當於@Autowired+@Qualifier
@Value:
只能注入基本型別等資料,不能注入bean型別,可以使用${}在資原始檔中獲取資料,前提是,外部資原始檔被載入。
-
作用域的
@Scope:
用於指定bean的作用域,一般就是singleton和prototype
-
生命週期相關的
@PostConstruct:
用於指定某一個方法為初始化方法
@PreDestroy:
用於指定某一個方法為銷燬方法
-
其他配置類相關的
@Configuration:
宣告一個類為配置類,用於替代applicationContext.xml的
@ComponentScan:
用於開啟註解掃描的包
@Import:
用於匯入其他類的
@PropertySource:
用於載入外部資原始檔的
@Bean:
用於將方法返回的bean型別的物件裝配到容器中
-
Junit相關的
@RunWith:
用於替換底層的執行器,初始化spring容器的
@ContextConfiguration
用於指定配置檔案或者配置類的