Spring基于注解管理bean實現(xiàn)方式講解
一、標記與掃描
①注解
和 XML 配置文件一樣,注解本身并不能執(zhí)行,注解本身僅僅只是做一個標記,具體的功能是框架檢測到注解標記的位置,然后針對這個位置按照注解標記的功能來執(zhí)行具體操作。 本質(zhì)上:所有一切的操作都是 Java 代碼來完成的, XML 和注解只是告訴框架中的 Java 代碼如何執(zhí)行。 舉例:元旦聯(lián)歡會要布置教室,藍色的地方貼上元旦快樂四個字,紅色的地方貼上拉花,黃色的地方貼上氣球。

班長做了所有標記,同學們來完成具體工作。墻上的標記相當于我們在代碼中使用的注解,后面同學們做的工作,相當于框架的具體操作。
②掃描
Spring 為了知道程序員在哪些地方標記了什么注解,就需要通過掃描的方式,來進行檢測。然后根據(jù)注解進行后續(xù)操作。
③標識組件的常用注解
@Component :將類標識為普通組件
@Controller :將類標識為控制層組件
@Service :將類標識為業(yè)務層組件
@Repository :將類標識為持久層組件
問:以上四個注解有什么關系和區(qū)別?
通過查看源碼我們得知, @Controller 、 @Service 、 @Repository 這三個注解只是在 @Component 注解的基礎上起了三個新的名字。
對于 Spring 使用 IOC 容器管理這些組件來說沒有區(qū)別。所以 @Controller 、 @Service @Repository 這三個注解只是給開發(fā)人員看的,讓我們能夠便于分辨組件的作用。 注意:雖然它們本質(zhì)上一樣,但是為了代碼的可讀性,為了程序結構嚴謹我們肯定不能隨便胡亂標記。
④創(chuàng)建組件
創(chuàng)建控制層組件
@Controller
public class UserController {
}創(chuàng)建接口 UserService
public interface UserService {
}創(chuàng)建業(yè)務層組件 UserServiceImpl
@Service
public class UserServiceImpl implements UserService {
}創(chuàng)建接口 UserDao
public interface UserDao {
}創(chuàng)建持久層組件 UserDaoImpl
@Repository
public class UserDaoImpl implements UserDao {
}⑤掃描組件
情況一:最基本的掃描方式(beans里面配置)
<context:component-scan base-package="com.atguigu.spring">
</context:component-scan>測試:
@Test
public void test2(){
ConfigurableApplicationContext ioc = new ClassPathXmlApplicationContext("spring-autowire-xml.xml");
UserController userController = ioc.getBean(UserController.class);
System.out.println(userController);
UserDaoImpl userDao = ioc.getBean(UserDaoImpl.class);
System.out.println(userDao);
UserService userService = ioc.getBean(UserService.class);
System.out.println(userService);
}
情況二:指定要排除的組件
type="annotation",根據(jù)注解排除,expression中設置要排除的注解的全類名:
<!-- context:exclude-filter標簽:指定排除規(guī)則 -->
<!--
type:設置排除或包含的依據(jù)
type="annotation",根據(jù)注解排除,expression中設置要排除的注解的全類名
type="assignable",根據(jù)類型排除,expression中設置要排除的類型的全類名
-->
<context:component-scan base-package="com.atguigu.spring">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan> public void test2(){
ConfigurableApplicationContext ioc = new ClassPathXmlApplicationContext("spring-autowire-xml.xml");
UserController userController = ioc.getBean(UserController.class);
System.out.println(userController);
UserDaoImpl userDao = ioc.getBean(UserDaoImpl.class);
System.out.println(userDao);
UserService userService = ioc.getBean(UserService.class);
System.out.println(userService);
}
將UserController 注釋:
public void test2(){
ConfigurableApplicationContext ioc = new ClassPathXmlApplicationContext("spring-autowire-xml.xml");
// UserController userController = ioc.getBean(UserController.class);
// System.out.println(userController);
UserDaoImpl userDao = ioc.getBean(UserDaoImpl.class);
System.out.println(userDao);
UserService userService = ioc.getBean(UserService.class);
System.out.println(userService);
}
type="assignable",根據(jù)類型排除,expression中設置要排除的類型的全類名 :
<context:component-scan base-package="com.atguigu.spring">
<!-- <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>-->
<context:exclude-filter type="assignable" expression="com.atguigu.spring.Dao.impl.UserDaoImpl"/>
</context:component-scan> public void test2(){
ConfigurableApplicationContext ioc = new ClassPathXmlApplicationContext("spring-autowire-xml.xml");
UserController userController = ioc.getBean(UserController.class);
System.out.println(userController);
UserDaoImpl userDao = ioc.getBean(UserDaoImpl.class);
System.out.println(userDao);
UserService userService = ioc.getBean(UserService.class);
System.out.println(userService);
}
將UserDaoImpl 注釋掉:
public void test2(){
ConfigurableApplicationContext ioc = new ClassPathXmlApplicationContext("spring-autowire-xml.xml");
UserController userController = ioc.getBean(UserController.class);
System.out.println(userController);
// UserDaoImpl userDao = ioc.getBean(UserDaoImpl.class);
// System.out.println(userDao);
UserService userService = ioc.getBean(UserService.class);
System.out.println(userService);
}
情況三:僅掃描指定組件
<context:component-scan base-package="com.atguigu" use-default-filters="false"> <!-- context:include-filter標簽:指定在原有掃描規(guī)則的基礎上追加的規(guī)則 --> <!-- use-default-filters屬性:取值false表示關閉默認掃描規(guī)則 --> <!-- 此時必須設置use-default-filters="false",因為默認規(guī)則即掃描指定包下所有類 --> <!-- type:設置排除或包含的依據(jù) type="annotation",根據(jù)注解排除,expression中設置要排除的注解的全類名 type="assignable",根據(jù)類型排除,expression中設置要排除的類型的全類名 --> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> <!--<context:include-filter type="assignable" expression="com.atguigu.controller.UserController"/>--> </context:component-scan>
⑥組件所對應的 bean 的 id 在我們使用 XML 方式管理 bean 的時候,每個 bean 都有一個唯一標識,便于在其他地方引用?,F(xiàn)在使用注解后,每個組件仍然應該有一個唯一標識。
默認情況
類名首字母小寫就是 bean 的 id 。例如: UserController 類對應的 bean 的 id 就 userController 。
自定義 bean 的 id
可通過標識組件的注解的 value 屬性設置自定義的 bean 的 id
@Service("userService")
// 默認為 userServiceImpl
public class UserServiceImpl implements UserService {}
public void test2(){
ConfigurableApplicationContext ioc = new ClassPathXmlApplicationContext("spring-autowire-xml.xml");
UserController userController = ioc.getBean("userController",UserController.class);
System.out.println(userController);
UserDao userDao = ioc.getBean("userDaoImpl",UserDao.class);
System.out.println(userDao);
UserService userService = ioc.getBean("userServiceImpl",UserService.class);
System.out.println(userService);
}二、基于注解的自動裝配
①場景模擬
參考基于 xml 的自動裝配
在 UserController 中聲明 UserService 對象
在 UserServiceImpl 中聲明 UserDao 對象
②@Autowired注解
在成員變量上直接標記 @Autowired 注解即可完成自動裝配,不需要提供 setXxx() 方法。以后我們在項目中的正式用法就是這樣。
@Controller
public class UserController {
@Autowired
private UserService userService;
public void saveUser(){
userService.saveUser();
}
}public interface UserService {
void saveUser();
}@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public void saveUser() {
userDao.saveUser();
}
}public interface UserDao {
void saveUser();
}@Repository
public class UserDaoImpl implements UserDao {
@Override
public void saveUser() {
System.out.println("保存成功");
}
}③@Autowired注解其他細節(jié)
@Autowired 注解可以標記在構造器和 set 方法上
@Controller
public class UserController {
private UserService userService;
@Autowired
public UserController(UserService userService){
this.userService = userService;
}
public void saveUser(){
userService.saveUser();
}
}@Controller
public class UserController {
private UserService userService;
@Autowired
public void setUserService(UserService userService){
this.userService = userService;
}
public void saveUser(){
userService.saveUser();
}
}④@Autowired工作流程

首先根據(jù)所需要的組件類型到 IOC 容器中查找
- 能夠找到唯一的bean:直接執(zhí)行裝配
- 如果完全找不到匹配這個類型的bean:裝配失敗
- 和所需類型匹配的bean不止一個
→沒有@Qualifier注解:根據(jù)@Autowired標記位置成員變量的變量名作為bean的id進行匹配
能夠找到:執(zhí)行裝配
找不到:裝配失敗
→使用@Qualifier 注解:根據(jù) @Qualifier 注解中指定的名稱作為 bean 的 id 進行匹配
能夠找到:執(zhí)行裝配
找不到:裝配失敗
@Controller
public class UserController {
@Autowired
@Qualifier("userServiceImpl")
private UserService userService;
public void saveUser(){
userService.saveUser();
}
}@Autowired中有屬性required,默認值為true,因此在自動裝配無法找到相應的bean時,會裝配失敗
可以將屬性 required 的值設置為 true ,則表示能裝就裝,裝不上就不裝,此時自動裝配的屬性為默認值
但是實際開發(fā)時,基本上所有需要裝配組件的地方都是必須裝配的,用不上這個屬性。
到此這篇關于Spring基于注解管理bean實現(xiàn)方式講解的文章就介紹到這了,更多相關Spring管理bean內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
一天時間用Java寫了個飛機大戰(zhàn)游戲,朋友直呼高手
前兩天我發(fā)現(xiàn)論壇有兩篇飛機大戰(zhàn)的文章異?;鸨?但都是python寫的,竟然不是我大Java,說實話作為老java選手,我心里是有那么一些失落的,今天特地整理了這篇文章,需要的朋友可以參考下2021-05-05
Spring Boot + Mybatis 實現(xiàn)動態(tài)數(shù)據(jù)源案例分析
這篇文章主要介紹了Spring Boot + Mybatis 實現(xiàn)動態(tài)數(shù)據(jù)源,需要的朋友可以參考下2018-11-11
Java多線程導致CPU占用100%解決及線程池正確關閉方式
1000萬表數(shù)據(jù)導入內(nèi)存數(shù)據(jù)庫,按分頁大小10000查詢,多線程,15條線程跑,最后發(fā)現(xiàn)CPU占用100%卡死,那么如何解決,本文就來介紹一下,感興趣的朋友可以了解一下2021-05-05
詳解SpringBoot中@SessionAttributes的使用
這篇文章主要通過示例為大家詳細介紹了SpringBoot中@SessionAttributes的使用,文中的示例代碼講解詳細,感興趣的小伙伴可以了解一下2022-07-07
java使用apache commons連接ftp修改ftp文件名失敗原因
這篇文章主要介紹了java使用apache commons連接ftp修改ftp文件名失敗原因解析,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-08-08
Java中一維二維數(shù)組的靜態(tài)和動態(tài)初始化
今天通過本文給大家分享Java中的數(shù)組,包括一維數(shù)組和二維數(shù)組的靜態(tài)初始化和動態(tài)初始化問題,感興趣的朋友一起看看吧2017-10-10
Java操作Mongodb數(shù)據(jù)庫實現(xiàn)數(shù)據(jù)的增刪查改功能示例
這篇文章主要介紹了Java操作Mongodb數(shù)據(jù)庫實現(xiàn)數(shù)據(jù)的增刪查改功能,結合完整實例形式分析了java針對MongoDB數(shù)據(jù)庫的連接、增刪改查等相關操作技巧,需要的朋友可以參考下2017-08-08
MyBatis-Plus中實現(xiàn)自定義復雜排序邏輯的詳細步驟
這篇文章主要介紹了MyBatis-Plus中實現(xiàn)自定義復雜排序邏輯,通過使用MyBatis-Plus的QueryWrapper和SQL原始片段,我們可以靈活地實現(xiàn)復雜的數(shù)據(jù)排序邏輯,這種方法尤其適用于需要對數(shù)據(jù)進行特定規(guī)則排序的場景,需要的朋友可以參考下2024-07-07
SpringBoot服務監(jiān)控機制原理解析(面試官常問)
這篇文章主要介紹了SpringBoot服務監(jiān)控機制原理解析(面試官常問),本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-04-04

