SpringBoot對不同Bean注解的區(qū)別和使用場景說明
對不同Bean注解的區(qū)別和使用場景
什么是Bean?
談Bean的潛臺詞是在說Spring中的Bean,我們都知道Spring中的BeanFactory,而Bean這個概念也是由此而來。在Spring中,只要一個類能被實例化,并被Spring容器管理,這個類就稱為一個Bean,或者SpringBean.
除此之外,我們還聽到一些其他的詞:
JavaBean、POJO、VO、DTO
這些叫法又是什么意思?使用的場景又是什么?
JavaBean
一個JavaBean是一個遵循Sun公司JavaBean規(guī)范的類。JavaBean可以理解為java中可以復用的組件,它滿足下面條件:
- 有一個公共的缺省構(gòu)造方法
- 這個類的屬性使用getter和setter來訪問,并且命名遵從標準的規(guī)范
- 這個類可以序列化
POJO(Plain Ordinary Object )
POJO是一個歷史遺留名稱,為什么這樣講?因為POJO是用來指明該對象不同于Entity Beans
EntityBeans是EJB中的概念,而EJB在Spring出現(xiàn)后,就漸漸淡出了歷史的舞臺。所以,POJO在Martin Fowler提出時,就是指那些沒有實現(xiàn)任何EJB接口的普通java類。而延用至今,嚴格講,所有的java類,都是POJO,因為現(xiàn)在沒有人在使用ejb這些老古董了。但是有時我們?yōu)榱藚^(qū)分Spring Bean,可以將沒有被Spring管理的類稱為POJO。
VO (Value Object)
VO指一個對象例如 java.lang.Integer 它持有一些數(shù)據(jù),或數(shù)據(jù)對象。這個概念是 Martin Fowler企業(yè)應用架構(gòu)中提出的概念。
DTO (Data Transfer Object)
DTO也是EJB種提出的一個概念,目的就是在數(shù)據(jù)傳輸時,通過直接傳輸對象,在網(wǎng)絡中傳輸數(shù)據(jù)。
小結(jié):
所以對我們而言,VO和DTO沒有區(qū)別(但是Martin Fowler可能用它們表示了不同的細分概念),而大多數(shù)時候,它們遵循JavaBean規(guī)范,所以它們也都是JavaBean。當然,它們都是POJO。
可以看出,它們本質(zhì)上都是在指一個java對象,為了區(qū)分場景和功能,有了不同的叫法。開發(fā)中有時還會出現(xiàn),Entity, Domain等。用來表示對實體的映射,或表的映射。一般可以這樣做來規(guī)范開發(fā):
- 對于Spring管理的對象,稱為Bean
- 映射到數(shù)據(jù)表的對象實體類,稱為entity,放在entity目錄
- 對于接口用于封裝數(shù)據(jù),比如接受一個json入?yún)?,為了方便,定義一個對象封裝參數(shù),可以叫dto (或pojo) 放在pojo包,以表明它不是某個表的映射類。
注解@Bean @Component …等都有什么區(qū)別?
用SpringBoot開發(fā)應用時,我們會用注解將對象交給Spring容器管理。這些注解包括:
@Component ,@Service, @Bean, @Controller ,@Repository
這些注解本質(zhì)上,都是Spring標識,用來進行Bean的自動檢測。標注這些注解的類會被Spring容器管理。
那為何要有這些分類,為何不使用一個注解就來搞定所有的工作?
首先這幾個注解根據(jù)語義,用在不同的層面
@Componet
一般的組件@Service
是Service層組件@Bean
這個要和@Configuration一塊使用,后邊再說@Controller
是用在SpringMVC控制層@Repository
是數(shù)據(jù)訪問層
Spring這樣設計,是因為,這些注解不光是要做自動檢測。同時有不同的功能,比如@Repository注解,Spring會增加增強處理,進行相關(guān)的異常處理。
@Controller的bean會處理網(wǎng)絡請求相關(guān)邏輯。所以你給所有的Bean都標注同一個注解,確實都會注入Spring容器,但是功能可能就會失效。
而且隨著Spring版本升級,可能會增加更多差異化處理。所以我們應該按照規(guī)范來注解。
再說到@Bean,我們知道Spring早期,還是通過xml配置Bean例如:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" ? ? xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" ? ? xsi:schemaLocation="http://www.springframework.org/schema/beans? ? ? http://www.springframework.org/schema/beans/spring-beans.xsd? ? ? http://www.springframework.org/schema/context? ? ? http://www.springframework.org/schema/context/spring-context.xsd"> ? ? ? ? ? <bean id="operations" ? ?class="com.howtodoinjava.spring.beans.Operations"></bean> ? ? <bean id="employee" ?class="com.howtodoinjava.spring.beans.Employee"></bean> ? ? ? </beans>?
現(xiàn)在,你可以理解@Configuration注解的類就是一個xml配置文件,中間@Bean注解就是xml中的bean節(jié)點
@Configuration public class BeanConfiguration { ? ? ?@Bean ? ? ?public Operations operation(){ ? ? ? ? ?return new Operations(); ? ? ?} ? ? ?@Bean ? ? ?public Employee employee(){ ? ? ? ? ?return new Employee(); ? ? ?} ? ?? }
這兩種方式都是將@Bean注解返回值注入Spring容器。SpringBoot在啟動時,會掃描@Configuration注解,進行注入。
SpringBoot注入對象沖突如何解決?
好了,現(xiàn)在我們終于把想要的組件交給Spring容器管理。我們該如何使用?
我們可以用Spring上下文,獲取需要的對象
public static void main(String[] args) { ?? ??? ?ApplicationContext application = SpringApplication.run(ConsumerApplication.class, args); ?? ??? ?application.getBean(Employee.class); }
一般我們用@Autowire 注解,獲取容器中的bean
@Autowire private Employee employee;
有時我們在容器中需要注入一個類的多個實例,以滿足需求。
比如一個接口的實現(xiàn)類有兩個,如果直接通過@Component注入容器,則會報錯。
如何區(qū)分?
@Component("bean01") public class Bean01 implement AA{ ? ?? } @Component("bean02") public class Bean02 implement AA{ ? ?? }
沒錯,通過在注解中標識一個名稱,來區(qū)分該對象的不同實例。
獲取時:最終會初始化一個Bean01
@Autowire @Qualifier("bean01") private AA a;
這樣有個問題,就是每次使用都需要顯示聲明@Qualifier來指定。有的場景下,我們可能想默認使用一個,其他情況再顯式指定。這就涉及到@Primary
在注解時,標注了@Primary的Bean在沒有指定的情況下,會默認加載。
比如:
@Component @Primary public class Bean01 implement AA{ ? ?? } @Component("bean02") public class Bean02 implement AA{ ? ?? }
使用時: 默認初始化的就是Bean01
@Autowire private AA a;
SpringBoot的各種注解
@Configuration
表示當前類可以用作配置文件使用
可以在這個類中使用@bean注解來創(chuàng)建對象(類似于單例模式的餓漢式)。
方法中需要有返回值+使用new這個關(guān)鍵字
spring會把這個返回值放入spring容器中;
在后面的方法中如果要調(diào)用這個方法(@bean中有個屬性name,命名name的值,在后面的@resource中使用使用按照名稱注入)沒有使用name這個屬性的話,默認情況下@bean方法的方法名;
@importResource
:用來導入xml文件,xml文件里面也是聲明java對象,同樣也是導入到spring容器中@propertySource
:用來導入property文件
可以和@value一起使用,@value來用讀取property文件的內(nèi)容;
@componentScan
:用來指定掃描注解的位置,掃描把掃描到的注解生成對象放入spring容器中,
屬性:basePackage:指定掃描到包的位置
默認情況下是掃描當前包和子包的位置
@SpringBootApplication
由三個主要注解組合而成:@SpringBootConfiguration+@EnableAutoConfiguration+@ComponentScan
@SpringBootCOnfiguration
:表示這個類可以作為配置類使用;@EnableAutoConfiguration
:啟動自動注入,把java文件配置好,直接注入到Spring容器中;@ComponentScan
:表示文件下的注解,用來創(chuàng)建對象@ConfigurationProperties
:使用在java類上,表示使用K-V自動注入到對應的java屬性上,
參數(shù)prefix:把properties文件中對應的前綴.后面的屬性對應到properties文件的屬性中(使用在類上,所以在屬性上可以自動賦值)
和@value是兩種用法
@controller、@service、@Repository、@component
這些注解使用在java類上,componentScan會掃描這些完成對象的創(chuàng)建
@controller
使用在控制層,完成接收請求參數(shù),調(diào)用service層完成用戶的請求,返回視圖層給用戶;@Service
:業(yè)務層的邏輯,調(diào)用dao層完成用戶對數(shù)據(jù)庫的操作,將處理結(jié)果返回給controller;@Repository
:使用對數(shù)據(jù)庫進行持久化操作(保證用戶的數(shù)據(jù)可以寫入到數(shù)據(jù)庫中),將處理結(jié)果返回給service層
##在SpringBoot中使用@mapper代替這個注解。用來告訴mybatis創(chuàng)建這個對象的動態(tài)代理對象
##@mapperScan(basePackage:指定的mapper文件的路徑),使用在主啟動類上,省的一個一個dao層都要使用到@mapper
@component
:用來創(chuàng)建對象,但是對象沒有前面三個有特殊的功能@transaction
:表示開啟事務(一般使用在service層)有五個參數(shù)
1、傳播行為 2、隔離級別 3、超時行為 4、回滾規(guī)則 5、是否只讀
@RestController ? = @responseBody+@controller
使用在類上:表示這個類是控制層,而且類中的所有方法加上@responseBody這個注解
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
spring @Scheduled注解的使用誤區(qū)及解決
這篇文章主要介紹了spring @Scheduled注解的使用誤區(qū)及解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11Maven發(fā)布封裝到中央倉庫時候報錯:no default secret key
這篇文章主要介紹了Maven發(fā)布封裝到中央倉庫時候報錯:no default secret key,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-12-12spring boot+jwt實現(xiàn)api的token認證詳解
這篇文章主要給大家介紹了關(guān)于spring boot+jwt實現(xiàn)api的token認證的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一學習學習吧2018-12-12spring boot + jpa + kotlin入門實例詳解
這篇文章主要介紹了spring boot + jpa + kotlin入門實例詳解 ,需要的朋友可以參考下2017-07-07JAVA實現(xiàn)連接本地打印機并打印文件的實現(xiàn)代碼
這篇文章主要介紹了JAVA實現(xiàn)連接本地打印機并打印文件的實現(xiàn)代碼,需要的朋友可以參考下2019-10-10java.sql.SQLException:?connection?holder?is?null錯誤解決辦法
這篇文章主要給大家介紹了關(guān)于java.sql.SQLException:?connection?holder?is?null錯誤的解決辦法,這個錯誤通常是由于連接對象為空或未正確初始化導致的,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2024-02-02