談談你對Spring Bean的理解

語言: CN / TW / HK

大家好,我是被程式設計耽誤的文藝Tom。

前幾天,有位同學向我反饋,說在面試中問到這樣這樣一個面試題:談談你對Spring Bean的理解。今天咱們就針對這樣一個面試題,給大家做一個詳細的介紹。我一共分三段來介紹,首先,介紹什麼是Spring Bean?然後,定義Spring Bean有哪些方式?,最後,給大家介紹Spring容器是如何載入Bean的?

咱們先來看什麼是Spring Bean?

1、什麼是Spring Bean?

Spring Bean是Spring中最基本的組成單元,Spring 官方文件對 Bean 的解釋是這樣的:

In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assembled, and managed by a Spring IoC container.

翻譯過來就是:

在 Spring 中,構成應用程式主幹並由Spring IoC容器管理的物件稱為Bean。Bean是一個由Spring IoC容器例項化、組裝和管理的物件。

從官方定義中,我們可以提取出以下資訊:

1、Bean是物件,一個或者多個不限定。

2、Bean託管在Spring中一個叫IoC的容器中。

3、我們的程式是由一個個Bean構成的。

Spring是通過宣告式配置的方式來定義Bean的,所有建立Bean需要的前置依賴或者引數都是通過配置檔案先宣告,Spring啟動以後會解析這些宣告好的配置內容。那麼,我們該如何去定義Spring中的Bean呢?

2、定義Spring Bean有哪些方式?

一般來說,Spring Bean的定義配置有三種方式:

第一種:基於XML的方式配置

這種配置方式主要適用於以下兩類場景:

1、Bean實現類來自第三方類庫、比如DataSource等

2、需要定義名稱空間的配置,如:context、aop、mvc等。

舉個例子,來看一段程式碼

<beans>     <import resource=“resource1.xml” />//匯入其他配置檔案Bean的定義     <import resource=“resource2.xml” />     <bean id="userService" class="com.gupaoedu.vip.UserService" init-method="init" destory-method="destory">      </bean>     <bean id="message" class="java.lang.String">       <constructor-arg index="0" value="test"></constructor-arg>     </bean> </beans>

這段程式碼是標準的Spring配置內容,咱們從上往下來看,首先匯入一個叫做resource1.xml的標準配置檔案,然後,匯入了第二個標準的配置檔案resource2.xml,接著,定義了一個叫做userService的Bean,對應的類是com.gupaoedu.vip.UserService,並且聲明瞭在userService例項化之後要呼叫init()方法,在userService銷燬之後呼叫destory()方法。

第二種:基於註解掃描的方式配置

這種配置方式主要適用於:在開發中需要引用的類,如Controller、Service、Dao等。

兩種配置方法:

<context:component-scan base-package="com.gupaoedu.vip">    <context:include-filter type="regex" expression="com.gupaoedu.vip.mall.*"/>//包含的目標類   <context:exclude-filter type="aspectj" expression="com.gupaoedu.vip.mall..*Controller+"/>   //排除的目標類 </context:component-scan>

在這段配置中,context:component-scan相當於使用了Spring內建的掃描註解的元件 @ComponentScan ,聲明瞭需要掃描的基礎包路徑com.gupaoedu.vip,把所有com.gupaoedu.vip.mall下面的子包全部納入掃描範圍。並且排除了com.gupaoedu.vip.mall 包下面所有以Controller結尾或者包含Controller結尾的類。

使用Spring容器管理元件的beanName規則,預設是類名首字母變小寫,可以自己修改。Spring主要提供了4種內建的註解用來宣告Bean。它們分別是@Controller,宣告為控制層元件的Bean,@Service,宣告為業務邏輯層元件的Bean,@Repository,宣告為資料訪問層元件的Bean,當對元件的層次難以定位的時候使用@Component註解來宣告。

Spring提供了四個註解,這些註解的作用與上面的XML定義bean效果一致,在於將元件交給Spring容器管理。元件的名稱預設是類名(首字母變小寫),可以自己修改:

第三種:基於Java類的配置

這種配置方式主要適用於以下兩類場景:

1、需要通過程式碼控制物件建立邏輯的場景;

2、實現零配置,消除XML配置檔案的場景。

同樣還是舉個例子,來看一段程式碼:

``` @Configuration   public class BeansConfiguration {          @Bean       public Student student(){                  Student student = new Student();         student.setName("張三");         student.setTeacher(teacher());         return student;              }  

@Bean       public Teacher teacher(){                  Teacher teacher = new Teacher();         teacher.setName("Tom");         return teacher;              }      } ```

通過分析這段程式碼,我可以瞭解到使用基於類的配置需要以下步驟:

1、首先,在BeansConfiguration類上配置@Configuration註解,表示將BeansConfiguration類將定義Bean的元資料

2、在方法上使用@Bean註解,方法名預設就是Bean的名稱,方法返回值就是Bean的例項。

3、通過AnnotationConfigApplicationContext或子類來啟動Spring容器,從而載入這些已經宣告好的註解配置。

最後,總結一下,定義Spring Bean三種方式,分別是:基於XML的方式配置、基於註解掃描的方式配置、基於元資料類的配置。

那麼Bean的配置定義好以後,Spring又是如何載入這些Bean配置並建立Bean例項呢?

3、Spring容器如何載入Bean?

Spring解析這些宣告好的配置內容,將這些配置內容都轉化為BeanDefinition物件,BeanDefinition中幾乎儲存了配置檔案中宣告的所有內容,再將BeanDefinition存到一個叫做beanDefinitionMap中。以beanName作為Key,以BeanDefinition物件作為Value。之後Spring容器,根據beanName找到對應的BeanDefinition,再去選擇具體的建立策略。而Spring具體的建立策略如圖所示,大家想要高清無碼圖的可以在評論區留言。

關於Spring Bean的面試題解析就到這裡,相信大家也已經理解。如果想看Spring BeanDefiniton定義的小夥伴,可以關注我後續的更新內容。

S信【Tom】或【666】即可免費領取需要更多幹貨內容,還有海量面試資料,只彈乾貨不慘水!

本文為“Tom彈架構”原創,轉載請註明出處。技術在於分享,我分享我快樂!\ 如果本文對您有幫助,歡迎關注和點贊;如果您有任何建議也可留言評論或私信,您的支援是我堅持創作的動力。關注微信公眾號『 Tom彈架構 』可獲取更多技術乾貨!

關注微信公眾號『 Tom彈架構 』可獲取更多技術乾貨!往期影片已經整理成文件形式,需要的小夥伴點個關注,搜尋下方名片!我是被程式設計耽誤的文藝Tom,

什麼條件下會產出死鎖,如何避免死鎖?