自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

面試官:BeanFactory和FactoryBean有哪些區(qū)別?

開發(fā) 前端
通過分析DefaultListableBeanFactory#preInstantiateSingletons方法和FactoryBean#getObject的調(diào)用鏈路可以分析得到。

[[398320]]

區(qū)別

說實(shí)話,他倆除了名字比較像以外,好像沒有其他共同點(diǎn)了。

「BeanFactory和FactoryBean有哪些區(qū)別?」

  1. BeanFactory是一個(gè)最基礎(chǔ)的IOC容器,提供了依賴查找,依賴注入等基礎(chǔ)的功能
  2. FactoryBean是創(chuàng)建Bean的一種方式,幫助實(shí)現(xiàn)復(fù)雜Bean的創(chuàng)建

和BeanFactory相關(guān)的還有一個(gè)高頻的面試題

「ApplicationContext和BeanFactory有哪些區(qū)別?」

  1. BeanFactory是一個(gè)最基礎(chǔ)的IOC容器,提供了依賴查找,依賴注入等基礎(chǔ)的功能
  2. ApplicationContext繼承了BeanFactory,在BeanFactory的基礎(chǔ)上增加了企業(yè)級(jí)的功能,如AOP,資源管理(Resources)事件(Event),國(guó)際化(i18n),Environment抽象等

創(chuàng)建Bean的方式

常見的創(chuàng)建Bean的方式有如下四種

  1. 通過構(gòu)造器
  2. 通過靜態(tài)工廠方法
  3. 通過Bean工廠方法
  4. 通過FactoryBean
  1. @Data 
  2. @ToString 
  3. public class User { 
  4.  
  5.  private Long id; 
  6.  private String name
  7.  
  8.  public static User createUser() { 
  9.   User user = new User(); 
  10.   user.setId(1L); 
  11.   user.setName("li"); 
  12.   return user
  13.  } 
  1. public class UserFactory { 
  2.  
  3.  public User createUser() { 
  4.   return User.createUser(); 
  5.  } 
  1. public class UserFactoryBean implements FactoryBean { 
  2.  
  3.  @Override 
  4.  public Object getObject() throws Exception { 
  5.   return User.createUser(); 
  6.  } 
  7.  
  8.  @Override 
  9.  public Class<?> getObjectType() { 
  10.   return User.class; 
  11.  } 
  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <beans xmlns="http://www.springframework.org/schema/beans" 
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  4.     xsi:schemaLocation="http://www.springframework.org/schema/beans 
  5.         https://www.springframework.org/schema/beans/spring-beans.xsd"> 
  6.  
  7.  <!-- 構(gòu)造方法實(shí)例化 Bean --> 
  8.  <bean id="user-by-constructor" class="com.javashitang.domain.User"
  9.   <property name="id" value="1"/> 
  10.         <property name="name" value="li"/> 
  11.  </bean> 
  12.  
  13.  <!-- 靜態(tài)方法實(shí)例化 Bean --> 
  14.  <bean id="user-by-static-method" class="com.javashitang.domain.User" 
  15.     factory-method="createUser"/> 
  16.  
  17.  <bean id="userFactory" class="com.javashitang.factory.UserFactory"/> 
  18.  
  19.  <!-- Bean工廠方法實(shí)例化 Bean --> 
  20.  <bean id="user-by-factory" factory-bean="userFactory" factory-method="createUser"/> 
  21.  
  22.  <!-- FactoryBean實(shí)例化 Bean --> 
  23.  <bean id="user-by-factory-bean" class="com.javashitang.factory.UserFactoryBean"/> 
  24. </beans>
  1. public class BeanInstantiationDemo { 
  2.  
  3.  public static void main(String[] args) { 
  4.   BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/bean-instantiation-context.xml"); 
  5.   User user1 = beanFactory.getBean("user-by-constructor"User.class); 
  6.   User user2 = beanFactory.getBean("user-by-static-method"User.class); 
  7.   User user3 = beanFactory.getBean("user-by-factory"User.class); 
  8.   User user4 = beanFactory.getBean("user-by-factory-bean"User.class); 
  9.  } 

實(shí)現(xiàn)原理

在分析源碼之前,我們先明確2個(gè)概念

「factoryBean是我們配置到容器中的實(shí)現(xiàn)FactoryBean接口的Bean,而subBean是用FactoryBean創(chuàng)建出來的Bean」

在Spring容器啟動(dòng)的過程中,會(huì)實(shí)例化非延遲的單例Bean,即調(diào)用如下方法 DefaultListableBeanFactory#preInstantiateSingletons

調(diào)用FactoryBean#getObject的鏈路如下圖

通過分析DefaultListableBeanFactory#preInstantiateSingletons方法和FactoryBean#getObject的調(diào)用鏈路可以分析得到

  1. 單例的factoryBean對(duì)象本身會(huì)在spring容器啟動(dòng)時(shí)主動(dòng)初始化。而subBean的初始化則是在第一次從緩存中獲取factoryBean并且不為空才會(huì)觸發(fā)
  2. 如果factoryBean對(duì)象實(shí)現(xiàn)的接口是SmartFactoryBean且isEagerInit方法返回true,那么subBean對(duì)象也會(huì)在spring容器啟動(dòng)的時(shí)候主動(dòng)初始化
  3. 如果bean注冊(cè)的時(shí)候,beanName對(duì)應(yīng)的bean實(shí)例是一個(gè)factoryBean,那么我們通過getBean(beanName)獲取到的對(duì)象將會(huì)是subBean對(duì)象;如果要獲取工廠對(duì)象factoryBean,需要使用getBean("&" + beanName)
  4. 單例的subBean也會(huì)緩存在spring容器中,具體的容器是FactoryBeanRegistrySupport#factoryBeanObjectCache,一個(gè)Map

「建議大家看一下DefaultListableBeanFactory#preInstantiateSingletons方法和FactoryBean#getObject方法的調(diào)用鏈路,就能理解上面我說的流程了,我就不貼太多源碼了」

應(yīng)用

目前我只在Dubbbo源碼中看到了FactoryBean的應(yīng)用

「服務(wù)導(dǎo)出:在Dubbo中,服務(wù)提供者會(huì)被包裝成ServiceBean對(duì)象,當(dāng)監(jiān)聽到ContextRefreshedEvent事件時(shí)開始服務(wù)導(dǎo)出」

「服務(wù)調(diào)用:服務(wù)調(diào)用方會(huì)被包裝成ReferenceBean對(duì)象,ReferenceBean實(shí)現(xiàn)了FactoryBean接口和InitializingBean接口,創(chuàng)建subBean的邏輯在ReferenceBean#getObject方法中」

「Dubbo服務(wù)引入的時(shí)機(jī)有如下2種?!?/p>

  1. 餓漢式:init=true,在Bean生命周期的初始化階段會(huì)調(diào)用InitializingBean#afterPropertiesSet方法,而這個(gè)方法會(huì)調(diào)用ReferenceBean#getObject方法,完成subBean的創(chuàng)建,即ReferenceBean實(shí)例化時(shí)完成服務(wù)引入
  2. 懶漢式:init=false,在ReferenceBean對(duì)應(yīng)的服務(wù)被注入到其他類中時(shí),此時(shí)會(huì)調(diào)用AbstractApplicationContext#getBean,獲取ReferenceBean對(duì)象,因?yàn)镽eferenceBean實(shí)現(xiàn)了FactoryBean接口,所以會(huì)調(diào)用ReferenceBean#getObject方法,完成subBean的創(chuàng)建,即完成服務(wù)引入
  1. public class ReferenceBean<T> extends ReferenceConfig<T> implements FactoryBean, ApplicationContextAware, InitializingBean, DisposableBean { 
  2.  
  3.     @Override 
  4.     public Object getObject() { 
  5.         return get(); 
  6.     } 
  7.  
  8.     @Override 
  9.     @SuppressWarnings({"unchecked"}) 
  10.     public void afterPropertiesSet() throws Exception { 
  11.  
  12.         // 省略部分代碼 
  13.  
  14.         if (shouldInit()) { 
  15.             getObject(); 
  16.         } 
  17.     } 
  18.      

本文轉(zhuǎn)載自微信公眾號(hào)「Java識(shí)堂」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系Java識(shí)堂公眾號(hào)。

 

責(zé)任編輯:武曉燕 來源: Java識(shí)堂
相關(guān)推薦

2025-03-10 09:30:00

SpringJava開發(fā)

2023-07-06 14:24:23

Spring接口自定義

2023-02-20 08:08:48

限流算法計(jì)數(shù)器算法令牌桶算法

2021-07-01 07:51:45

React事件綁定

2021-09-30 07:57:13

排序算法面試

2023-02-17 08:10:24

2024-04-03 15:33:04

JWTSession傳輸信息

2024-09-19 08:42:43

2025-03-26 01:25:00

MySQL優(yōu)化事務(wù)

2024-03-07 17:21:12

HotSpotJVMHot Code

2024-02-26 14:07:18

2024-04-19 00:00:00

計(jì)數(shù)器算法限流算法

2024-03-12 14:36:44

微服務(wù)HTTPRPC

2025-03-10 00:00:00

property?attributeHTML

2025-03-10 11:40:00

前端開發(fā)HTML

2021-12-13 06:56:45

Comparable元素排序

2024-03-20 15:12:59

KafkaES中間件

2021-12-23 07:11:31

開發(fā)

2023-10-16 08:16:31

Bean接口類型

2021-07-02 07:06:20

React組件方式
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)