1. 程式人生 > >Spring系列之新註解配置+Spring整合junit+註解注入

Spring系列之新註解配置+Spring整合junit+註解注入

## Spring系列之註解配置 **Spring是輕程式碼而重配置的框架,配置比較繁重,影響開發效率,所以註解開發是一種趨勢,註解代替xml配置檔案可以簡化配置,提高開發效率** **你本來要寫一段很長的程式碼來構造一個Beam物件,但是如果使用註解的話只要使用一個註解符號即可** ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200921212449632.png#pic_center) **下面我們來講講一些經常使用的註解符號** @Component 使用類上用於例項化Bean @Controller 使用web層類上用於例項化Bean @Service 使用在Service層類上用於例項化service @Repository 使用在dao層類上用於例項化Bean @Autorwired 使用在欄位上用於根據型別依賴注入 @Qualifier 結合結合@Autowired一起使用根據名稱進行依賴注入 @Resource 相當於@Autowired+@Qualifier一起使用 @Scope 標註bean的範圍 @PostConstruct 使用該在方法上標註該方法是Bean的初始化方法 @PostDestory 使用在方法上標註該方法是Bean的銷燬方法 **這三個沒有什麼區別,不過是為了在後期讀程式碼的時候更加利於我們區分,比如看到@Controller就知道這是web層,看到@Service就知道這是service層** ```java @Component 使用類上用於例項化Bean @Controller 使用web層類上用於例項化Bean @Service 使用在Service層類上用於例項化service @Repository 使用在dao層類上用於例項化Bean ``` **所以我們只需講一個即可,其他的使用方法均相同,這裡我們使用@Component來講解** **定義一個userDaolmp類** ```java package com.pjh.dao; import com.pjh.dao.Imp.userdao; import org.springframework.stereotype.Component; @Component("userDaoImp") public class userDaoImp implements userdao { public void save() { System.out.println("save"); } } ``` **定義一個測試類測試** ```java @Test public void test(){ ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); userdao userDaoImp =(userdao) classPathXmlApplicationContext.getBean("userDaoImp"); userDaoImp.save(); } ``` **然後我們就發現瞭如下報錯** 由藍色的劃線部分我們可以看出問題是:沒有一個名叫userDaoImp的bean ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200922081316893.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3BqaDg4,size_16,color_FFFFFF,t_70#pic_center) **這是為什呢?因為我們雖然寫了註解,但是我們要讓applicationContext.xml知道我們使用了註解,要告訴他哪裡有個bean。所以我們在applicationContext中還需要加入以下配置** **名稱空間**:xmlns:context="http://www.springframework.org/schema/context **約束路徑**:http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd **註解的元件掃描:** **成功執行** ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200922082045847.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3BqaDg4,size_16,color_FFFFFF,t_70#pic_center) ## 接下來我們再來講講如何使用註解進行注入 **方式一:使用@Autowired+@Qualifier** **目的**:建立一個userdao類將其注入帶service類中 **userdao類程式碼** ```java package com.pjh.dao; import com.pjh.dao.Imp.userdao; import org.springframework.stereotype.Component; @Component("userDaoImp") public class userDaoImp implements userdao { public void save() { System.out.println("save"); } } ``` **service類程式碼** ```java package com.pjh.service.Imp; import com.pjh.dao.Imp.userdao; import com.pjh.dao.userDaoImp; import com.pjh.service.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Repository; import javax.annotation.Resource; import javax.xml.bind.SchemaOutputResolver; @Repository("serviceImp") public class serviceImp implements service { @Autowired @Qualifier("userDaoImp") private userDaoImp userDaoImp; public void save() { System.out.println("sssssss"); userDaoImp.save(); } } ``` **測試類** ```java @Test public void test(){ ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); service service =(service) classPathXmlApplicationContext.getBean("serviceImp"); service.save(); } ``` **結果** ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200922082716201.png#pic_center) **方式二:使用@Resource()** 就是把 @Autowired + @Qualifier("userDaoImp")換成@Resource(name="userDaoImp"),其餘程式碼均與方式一相同 ```java package com.pjh.service.Imp; import com.pjh.dao.Imp.userdao; import com.pjh.dao.userDaoImp; import com.pjh.service.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Repository; import javax.annotation.Resource; import javax.xml.bind.SchemaOutputResolver; @Repository("serviceImp") public class serviceImp implements service { /* @Autowired @Qualifier("userDaoImp")*/ @Resource(name="userDaoImp") private userDaoImp userDaoImp; public void save() { System.out.println("sssssss"); userDaoImp.save(); } } ``` **結果** ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200922084023247.png#pic_center) 令人蛋碎的事情來了,報錯了,意思是不支援版本5 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200922084125530.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3BqaDg4,size_16,color_FFFFFF,t_70#pic_center) **解決方案:** File->
setting下設定專案的jdk版本 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/2020092208475646.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3BqaDg4,size_16,color_FFFFFF,t_70#pic_center) File->ProjectStruct下設定版本 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200922084858890.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3BqaDg4,size_16,color_FFFFFF,t_70#pic_center) **結果** ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/2020092208495370.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3BqaDg4,size_16,color_FFFFFF,t_70#pic_center) **又報錯了,這。。。。。我tm心態崩了呀** ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200922085106310.png#pic_center) **根據報錯的內容是報了個空指標異常,這是為什麼呢?為什麼使用@Autowired + @Qualifier("userDaoImp")不報錯換成@Resource(name="userDaoImp")就報空指標呢** **原因**:jdk版本不支援 **解決方案:** 1.更換本地的jdk版本,最好jdk1.8以上,jdk9不支援有bug 2.再maven.pom檔案中引入如下依賴 ```java org.apache.tomcat
tomcat-annotations-api 7.0.47
``` **結果** 成功執行 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200922085638916.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3BqaDg4,size_16,color_FFFFFF,t_70#pic_center)**終於解決完了** ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200922085725833.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3BqaDg4,size_16,color_FFFFFF,t_70#pic_center) **使用@Scope註解標註Bean的範圍** **使用@Scope("prototype")** ```java package com.pjh.dao; import com.pjh.dao.Imp.userdao; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; @Component("userDaoImp") @Scope("prototype") public class userDaoImp implements userdao { public void save() { System.out.println("save"); } } ``` **測試程式碼** ```java @Test public void test(){ ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); userdao userdao =(userdao) classPathXmlApplicationContext.getBean("userDaoImp"); userdao userdao1 =(userdao) classPathXmlApplicationContext.getBean("userDaoImp"); System.out.println(userdao); System.out.println(userdao1); } ``` 結果 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200922090603570.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3BqaDg4,size_16,color_FFFFFF,t_70#pic_center) **使用@Scope("singleton")** ```java package com.pjh.dao; import com.pjh.dao.Imp.userdao; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; @Component("userDaoImp") @Scope("singleton") public class userDaoImp implements userdao { public void save() { System.out.println("save"); } } ``` **結果** ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/2020092209070120.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3BqaDg4,size_16,color_FFFFFF,t_70#pic_center) **在這裡順便給大家複習複習singleton與prototype的區別吧** **singleton** Bean的例項化個數:1個 Bean的例項化時機:當Spring核心配置檔案被載入時 Bean的生命週期: 物件建立:當應用載入時物件建立 物件執行:只要容器在,物件就一直活著 物件銷燬:當應用解除安裝,容器銷燬時 prototype:在使用getBean方法的時候建立bean **prototype** Bean的例項化格式:多個 Bean的例項化時機:當呼叫getBean()方法時,例項化Bean 物件建立:當使用物件時,建立新的物件例項 物件執行:只要物件在使用中,物件就一直存在 物件銷燬:物件長時間不使用,就會被java的垃圾回收機制回收 **初始化方法和銷燬方法** 初始化方法 @PostConstract ```java @PostConstruct public void constract(){ System.out.println("初始化方法"); } ``` 銷燬方法 @PostDestroy ```java @PreDestroy public void destroy(){ System.out.println("在物件銷燬前執行"); } ``` **@Value()進行注入** ```java package com.pjh.dao; import com.pjh.dao.Imp.userdao; import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; @Component("userDaoImp") @Scope("singleton") public class userDaoImp implements userdao { public void save() { System.out.println("save"); System.out.println("讀取配置檔案:"+one); System.out.println("普通型別:"+a); } @Value("${one.one}") private String one; @Value("4") private String a; } ``` **配置檔案資訊** ```java one.one=1 ``` **applicationContext中新增的內容** ```java
``` **測試程式碼** ```java @Test public void test(){ ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); userdao userdao =(userdao) classPathXmlApplicationContext.getBean("userDaoImp"); userdao.save(); } ``` 結果 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200922094336949.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3BqaDg4,size_16,color_FFFFFF,t_70#pic_center) 使用上面的註解還不可以全部替代xml配置檔案,還需要使用註解替代的配置如下 非自定義的Bean的配置: 載入properties檔案的配置: 註解掃描的配置: 引入其他檔案: ## Spring新註解 **@Configuration** 用於指定當前類是一個Spring配置類,建立容器時會從該類上載入註解,該類不能是匿名類與final類 **@ComponentScan** 用於指定Spring在初始化容器的時候要掃描包 作用與Spring中的此程式碼相同: **@Bean** 使用方法,將該方法的返回值返回到容器中 **@Import** 用於匯入其他配置類 **@PropertySource** 用於載入properties檔案中的配置 **案例** **核心配置類** ```java package com.pjh.config; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.stereotype.Component; /*標誌該類是核心配置類*/ @Configuration /*掃描包*/ @Component("com/pjh") /*匯入其他配置類*/ @Import(DataSourceConfig.class) public class Springconfig { } ``` **副配置類** ```java package com.pjh.config; import com.mchange.v2.c3p0.ComboPooledDataSource; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.PropertySource; import javax.sql.DataSource; import java.beans.PropertyVetoException; /*載入配置檔案*/ @PropertySource("classpath:jdbc.properties") public class DataSourceConfig { @Value("${jdbc.driver}") private String driver; @Value("${jdbc.url}") private String url; @Value("${jdbc.username}") private String username; @Value("${jdbc.password}") private String password; /*Spring會將當前方法的返回值以指定名稱儲存到Spring容器中*/ @Bean("dataSource") public DataSource getDataSource() throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass(driver); dataSource.setJdbcUrl(url); dataSource.setUser(username); dataSource.setPassword(password); return dataSource; } } ``` **測試函式** ```java @Test public void test() throws SQLException { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Springconfig.class); DataSource bean = (DataSource)applicationContext.getBean("dataSource"); Connection connection = bean.getConnection(); System.out.println(connection); } ``` **結果** 成功建立connection連線 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200922184238237.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3BqaDg4,size_16,color_FFFFFF,t_70#pic_center) ## Spring整合junit 為什麼使用Spring整合junit? 在測試類中每個類都要寫下面的兩行程式碼 ```java ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Springconfig.class); DataSource bean = (DataSource)applicationContext.getBean("dataSource"); ``` **這兩行程式碼的作用是獲取容器,不寫的話報空指標異常** 為了讓我們測試的時候不用進行反覆的寫上述兩行的操作,我們使用Spring來整合junit,用springjunit來建立spring容器, 我們只需將配置檔案的名稱告訴他們即可,將需要的bean直接在容器中進行注入 **Spring整合junit的步驟** 需要匯入的jar包 ```java org.springframework spring-test 5.0.2.RELEASE junit junit 4.13 test ``` ## 這是我spring系列的學習文章,我也會不斷的學習,文章如有錯誤還請批評指正,如有幫助大家可以點點關注,我們一同學習 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200922201913237.png#pic_