來源:blog.csdn.net/weixin_35544490/article/details/112143211
本文打算介紹幾個不太容易說出其區別,或者用途的 Spring 注解,比如 @Component
與 @Bean
的比較,@ControllerAdvice
是如何處理自定義異常的等等。
Spring 中的一些注解
1. @Component 和 @Bean 的區別是什么?
- 作用對象不同:
@Component
注解作用於類,而@Bean
注解作用於方法、 @Component
通常是通過路徑掃描來自動偵測以及自動裝配到 Spring 容器中(我們可以使用@ComponentScan
注解定義要掃描的路徑從中找出標識了需要裝配的類自動裝配到 Spring 的 bean 容器中)。@Bean
注解通常是我們在標有該注解的方法中定義產生這個 bean,@Bean
告訴了 Spring 這是某個類的實例,當我們需要用它的時候還給我。@Bean
注解比@Component
注解的自定義性更強,而且很多地方我們只能通過@Bean
注解來注冊 bean。比如當我們引用第三方庫中的類需要裝配到 Spring 容器時,只能通過@Bean
來實現。
@Bean
注解使用示例:
@Configuration
public class AppConfig {
@Bean
public TransferService transferService() {
return new TransferServiceImpl();
}
}
@Component 注解使用示例:
@Component
public class ServiceImpl implements AService {
....
}
下面這個例子是通過 @Component 無法實現的:
@Bean
public OneService getService(status) {
case (status) {
when 1:
return new serviceImpl1();
when 2:
return new serviceImpl2();
when 3:
return new serviceImpl3();
}
}
2. Autowire 和 @Resource 的區別
@Autowire
和@Resource
都可以用來裝配bean,都可以用於字段或setter方法。@Autowire
默認按類型裝配,默認情況下必須要求依賴對象必須存在,如果要允許 null 值,可以設置它的 required 屬性為 false。@Resource
默認按名稱裝配,當找不到與名稱匹配的 bean 時才按照類型進行裝配。名稱可以通過 name 屬性指定,如果沒有指定 name 屬性,當注解寫在字段上時,默認取字段名,當注解寫在 setter 方法上時,默認取屬性名進行裝配。
注意:如果 name 屬性一旦指定,就只會按照名稱進行裝配。
@Autowire
和@Qualifier
配合使用效果和@Resource
一樣:
@Autowired(required = false) @Qualifier("example")
private Example example;
@Resource(name = "example")
private Example example;
@Resource
裝配順序
- 如果同時指定 name 和 type,則從容器中查找唯一匹配的 bean 裝配,找不到則拋出異常;
- 如果指定 name 屬性,則從容器中查找名稱匹配的 bean 裝配,找不到則拋出異常;
- 如果指定 type 屬性,則從容器中查找類型唯一匹配的 bean 裝配,找不到或者找到多個拋出異常;
- 如果不指定,則自動按照 byName 方式裝配,如果沒有匹配,則回退一個原始類型進行匹配,如果匹配則自動裝配。
3. 將一個類聲明為 Spring 的 bean 的注解有哪些?
@Component
:通用的注解,可標注任意類為 Spring 的組件。如果一個 Bean 不知道屬於哪個層,可以使用@Component
注解標注。@Repository
:對應持久層即 Dao 層,主要用於數據庫相關操作。@Service
:對應服務層,主要設計一些復雜的邏輯,需要用到 Dao 層。@Controller
:對應 Spring MVC 控制層,主要用來接受用戶請求並調用 Service 層返回數據給前端頁面。@Configuration
:聲明該類為一個配置類,可以在此類中聲明一個或多個@Bean
方法。
4. @Configuration :配置類注解
@Configuration
表明在一個類里可以聲明一個或多個 @Bean
方法,並且可以由 Spring 容器處理,以便在運行時為這些 bean 生成 bean 定義和服務請求,例如:
@Configuration
public class AppConfig {
@Bean
public MyBean myBean() {
// instantiate, configure and return bean ...
}
}
我們可以通過 AnnotationConfigApplicationContext 來注冊 @Configuration
類:
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(AppConfig.class);
ctx.refresh();
MyBean myBean = ctx.getBean(MyBean.class);
// use myBean ...
另外也可以通過組件掃描(component scanning)來加載,@Configuration
使用 @Component
進行原注解,因此 @Configuration
類也可以被組件掃描到(特別是使用 XML 的 元素)。@Configuration
類不僅可以使用組件掃描進行引導,還可以使用 @ComponentScan
注解自行配置組件掃描:
@Configuration
@ComponentScan("com.acme.app.services")
public class AppConfig {
// various @Bean definitions ...
}
使用 @Configuration 的約束:
- 配置類必須以類的方式提供(比如不能是由工廠方法返回的實例)。
- 配置類必須是非 final 的。
- 配置類必須是非本地的(即可能不在方法中聲明),native 標注的方法。
- 任何嵌套的配置類必須聲明為 static。
- @Bean 方法可能不會反過來創建更多的配置類。
除了單獨使用 @Configuration
注解,我們還可以結合一些外部的 bean 或者注解共同使用,比如 Environment API
,@PropertySource
,@Value
,@Profile
等等許多,這里就不做詳細介紹了,更多的用法可以參看 Spring @Configuration 的相關文檔 。
5. @ControllerAdvice :處理全局異常利器
在 Spring 3.2 中,新增了 @ControllerAdvice
、@RestControllerAdvice
、@RestController
注解,可以用於定義 @ExceptionHandler
、@InitBinder
、@ModelAttribute
,並應用到所有 @RequestMapping
、@PostMapping
、@GetMapping
等這些 Controller 層的注解中。
推薦一個 Spring Boot 基礎教程及實戰示例:
https://github.com/javastacks/spring-boot-best-practice
默認情況下,@ControllerAdvice
中的方法應用於全局所有的 Controller。而使用選擇器 annotations()
,basePackageClasses()
和 basePackages()
(或其別名value())來定義更小范圍的目標 Controller 子集。如果聲明了多個選擇器,則應用 OR 邏輯,這意味着所選的控制器應匹配至少一個選擇器。請注意,選擇器檢查是在運行時執行的,因此添加許多選擇器可能會對性能產生負面影響並增加復雜性。
@ControllerAdvice
我們最常使用的是結合 @ExceptionHandler
用於全局異常的處理。可以結合以下例子,我們可以捕獲自定義的異常進行處理,並且可以自定義狀態碼返回:
@ControllerAdvice("com.developlee.errorhandle")
public class MyExceptionHandler {
/**
* 捕獲CustomException
* @param e
* @return json格式類型
*/
@ResponseBody
@ExceptionHandler({CustomException.class}) //指定攔截異常的類型
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) //自定義瀏覽器返回狀態碼
public Map>String, Object< customExceptionHandler(CustomException e) {
Map<String, Object> map = new HashMap<>();
map.put("code", e.getCode());
map.put("msg", e.getMsg());
return map;
}
}
更多信息可以參看 Spring @ControllerAdvice 的官方文檔。
6. @Component, @Repository, @Service 的區別
@Component
是一個通用的Spring容器管理的單例bean組件。而@Repository
, @Service
, @Controller
就是針對不同的使用場景所采取的特定功能化的注解組件。
因此,當你的一個類被@Component所注解,那么就意味着同樣可以用@Repository
, @Service
, @Controller
來替代它,同時這些注解會具備有更多的功能,而且功能各異。
最后,如果你不知道要在項目的業務層采用@Service
還是@Component
注解。那么,@Service
是一個更好的選擇。
總結
以上簡單介紹了幾種 Spring 中的幾個注解及代碼示例,就我個人而言,均是平時用到且不容易理解的幾個,或者容易忽略的幾個。當然,這篇文章並沒有完全介紹完,在今后還會繼續補充完善。
近期熱文推薦:
1.1,000+ 道 Java面試題及答案整理(2021最新版)
2.別在再滿屏的 if/ else 了,試試策略模式,真香!!
3.卧槽!Java 中的 xx ≠ null 是什么新語法?
4.Spring Boot 2.5 重磅發布,黑暗模式太炸了!
覺得不錯,別忘了隨手點贊+轉發哦!