一、回顧
但是我們之前MVC時候,在頁面上,為什只用Controller,不用其他的呢?
用其他的好使嗎?(我們可以在這里看到,出現404的字樣)
@Service @ResponseBody public class TestController {@RequestMapping("/test")public String test(){return "測試Controller和其他注解的區別";} }
但是Controller就是好使的,事實上Spring對Controller有更屌的權限
二、@Bean用法
五大注解只能加在類上,并且只能加在自己的代碼上
如果我引入一個第三方的jar包,也希望交給Spring管理,是沒有辦法加五大注解
第一個應用場景:可以使用@Bean, @Bean是方法注解
在這里,我們可以看到一個問題,就是兩個引用指向的是一個對象(看后面的那幾位,說明地址相同)
第二個應用場景:那么假如說要求是一個類,定義多個對象,比如說數據庫操作,定義多個數據源使用@Bean
@Bean相當于是一個上交作業的過程,交完了作業,要告訴老師,交完作業了
所以也就是說@Bean要搭配五大注解來使用并且當一個類型存在多個bean中,采用多個Bean的時候,我們就不能使用類型來獲取對象了。
我們上節課學的注釋
是getBean+方法名(小駝峰形式,特殊情況(兩個首字母都是大寫,那么她就會變成小寫)
@Bean需要加的是方法名(方法名不遵守小駝峰形式)
如何進行相應的傳遞參數
那么我們在應用中,一般不會讓寫死
假如對Bean的方法中的內容進行傳參數,則定義一個這種方法,當然現在這個也是死的,但是以后可以用這種方法變成“活的”
@Configuration public class BeanConfig {@Beanpublic String name(){return "zhangsan";}@Beanpublic UserInfo UserInfo(String string){UserInfo userInfo=new UserInfo();userInfo.setName(string);return userInfo;}
Spring的掃描文件約定
SpringBoot是屬于我們的開發框架(其實叫做開發框架,更感覺像是打開idea,后呈現的這個結構)
SpringBoot特點:約定大于配置,約定到,放到哪里就掃描當前文件夾里面的所有文件,但是假如說你硬是想在一個小的目錄里面去執行(也有方法,加路徑)(約定的體現之一掃描路徑,默認的掃描路徑是:啟動類所在的目錄及其子孫目錄)
放到這個文件夾里面會報錯
解決方式就是
//默認掃描當前類的目錄及子目錄在前面加上這個注解(路徑自己填)@ComponentScan("com.example")@ComponentScan("com.example") @SpringBootApplication public class IoCtryApplication {public static void main(String[] args) {//啟動類是幫助我們啟動spring,這個命令可以返回一個spring
DI詳解
DI依賴注入,屬性裝配“依賴裝配”,
只要加上這些依賴注入(就跟我們導包一樣,沒導包不能用)
1.屬性注入 @Autowired
(相當于導游,帶著去找這個東西)和上面那個匹配的一致,和那個@Bean傳遞參數一樣。
@Controller public class UserController { //??假如沒有下面的這個Autowired注釋,那么就會報空指針異常 @Autowired private UserService userService;public void prin(){userService.doService();System.out.println("春節快樂"); } }
UserController userController=context.getBean(UserController.class);userController.prin();
2.構造方法注入
如下圖
@Controller public class UserController { //@Autowired private UserService userService;private UserInfo userInfo; //??注意此時加完構造函數之后,還要把無參數的也寫一遍,因為無參數的構造函數,有很多東西在用,所以一旦經過修改,就會讓使用無參數的報錯。public UserController(){ } @Autowired public UserController(UserService userService){this.userService=userService; }public UserController(UserInfo userInfo,UserService userService){this.userService=userService;this.userInfo=userInfo;} public void prin(){userService.doService();System.out.println("春節快樂"); }
3.Setter方法注入
三種注入的優缺點
1.屬性注入:
優點:簡潔方便
缺點:只能用于IOC容器,如果非IOC容器無法使用,并且只有在使用的時候才會出現NPE(空指針異常),并且不能修飾Final。
2.構造函數注入:
優點:
(1).可以注入final屬性(通過構造方法的形式)。
(2).注入的對象不會被修改(因為除非你再new,不然構造方法不能被再次調用),依賴對象使用之前一定會被初始化,因為依賴在類的構造方法中執行的,構造方法是類加載階段就會執行的方法
(3).通用型好:構造方法是JDK支持的
缺點:
代碼會比較繁瑣
Setter注入
優點:方便類實例化之后,重新對該對象進行配置或者注入
缺點:不能修飾Final,注入的對象肯會被改變,因為setter方法可能會被多次調用,就有被修改的風險。
當程序同一個類型,多個對象時候,使用@AutoWired會報錯
這里說的情況是這樣的一個代碼
package com.example.IOCtry;import com.example.IOCtry.config.UserInfo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.stereotype.Controller;@Controller public class UserController { @Autowired //?? private UserService userService; @Autowired //?? private UserInfo userInfo; //注意此時加完構造函數之后,還要把無參數的也寫一遍,因為無參數的構造函數,有很多東西在用,所以一旦經過修改,就會讓使用無參數的報錯。//public UserController(){ //} // //public UserController(UserService userService){ // this.userService=userService; //} // // public UserController(UserInfo userInfo,UserService userService){ // this.userService=userService; // this.userInfo=userInfo; // } // @Autowired // public void setUserController(UserService userService){ // this.userService=userService; // } public void prin(){userService.doService();System.out.println(userInfo);System.out.println("春節快樂"); } }
改法一需要改屬性名字:讓屬性名和方法名字一致
package com.example.IOCtry;import com.example.IOCtry.config.UserInfo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.stereotype.Controller;@Controller public class UserController { @Autowired private UserService userService; @Autowired private UserInfo UserInfo1; //??這個名字改成和方法名字一摸一樣 //注意此時加完構造函數之后,還要把無參數的也寫一遍,因為無參數的構造函數,有很多東西在用,所以一旦經過修改,就會讓使用無參數的報錯。//public UserController(){ //} // //public UserController(UserService userService){ // this.userService=userService; //} // // public UserController(UserInfo userInfo,UserService userService){ // this.userService=userService; // this.userInfo=userInfo; // } // @Autowired // public void setUserController(UserService userService){ // this.userService=userService; // } public void prin(){userService.doService();System.out.println(UserInfo1);System.out.println("春節快樂"); } }
不想改名的第二種方法:加上@Primary//這個是在另一個類中搞的方法 package com.example.IOCtry.config;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary;@Configuration public class BeanConfig {@Beanpublic String name(){return "zhangsan";}@Beanpublic String name2(){return "wangwu";}// ??@Primary這個只有加上,程序才會不發生錯誤,會執行這個Setter方法@Beanpublic UserInfo UserInfo1(String name2){UserInfo userInfo=new UserInfo();userInfo.setName(name2);return userInfo;}@Beanpublic UserInfo userInfo2(){UserInfo userInfo=new UserInfo();userInfo.setId(2);userInfo.setAge(22);userInfo.setName("lclyr");return userInfo;}}
改法3(優先):使用@Qualifierpackage com.example.IOCtry;import com.example.IOCtry.config.UserInfo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; import org.springframework.stereotype.Controller;@Controller public class UserController { @Autowired private UserService userService; @Qualifier("userInfo2") //?? @Autowired private UserInfo userInfo; //注意此時加完構造函數之后,還要把無參數的也寫一遍,因為無參數的構造函數,有很多東西在用,所以一旦經過修改,就會讓使用無參數的報錯。//public UserController(){ //} // //public UserController(UserService userService){ // this.userService=userService; //} // // public UserController(UserInfo userInfo,UserService userService){ // this.userService=userService; // this.userInfo=userInfo; // } // @Autowired // public void setUserController(UserService userService){ // this.userService=userService; // } public void prin(){userService.doService();System.out.println(userInfo);System.out.println("春節快樂"); } }
改法4(優先):使用@Resource(name="userInfo2")
package com.example.IOCtry;import com.example.IOCtry.config.UserInfo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; import org.springframework.stereotype.Controller;import javax.annotation.Resource;@Controller public class UserController { @Autowired private UserService userService; //@Qualifier("userInfo2")@Resource(name="userInfo2") @Autowired private UserInfo userInfo; //注意此時加完構造函數之后,還要把無參數的也寫一遍,因為無參數的構造函數,有很多東西在用,所以一旦經過修改,就會讓使用無參數的報錯。//public UserController(){ //} // //public UserController(UserService userService){ // this.userService=userService; //} // // public UserController(UserInfo userInfo,UserService userService){ // this.userService=userService; // this.userInfo=userInfo; // } // @Autowired // public void setUserController(UserService userService){ // this.userService=userService; // } public void prin(){userService.doService();System.out.println(userInfo);System.out.println("春節快樂"); } }
三、常見面試題Autowired VS? Resource
@Autowired:是Spring開發的框架,@Resource是JDK提供的框架
@Autowired:默認是按照類型來去注入,假如說同一個類型存在多個對象,那么就按名稱匹配,假如名稱匹配不上,那么就會報錯,相對于Autowired來說,@Resource支持更多的參數設置,如name設置,根據名稱獲取Bean???????