2.2 spring5源碼系列 -- ioc加載的整體流程


之前我們知道了spring ioc的加載過程, 具體如下圖. 下面我們就來對照下圖, 看看ioc加載的源代碼.

 下面在用裝修類比, 看看個個組件都是怎么工作的.

 

接下來是源碼分析的整體結構圖. 對照上面的思路梳理出來的

 

一、源碼分析的入口 

通常,我們的入口都是從main方法進入. 這里我們也來定義一個main方法

public class MainStarter {
    public static void main(String[] args) { // 第一步: 通過AnnotationConfigApplicationContext讀取一個配置類 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainStarter.class); context.scan("package name"); Car car = (Car) context.getBean("car"); System.out.println(car.getName()); context.close(); } }

 

順便再來看看還有哪些相關的類

/**
 * 這是一個配置類,
 * 在配置類里面定義了掃描的包路徑com.lxl.www.iocbeanlifecicle
 * 這是會將這個包下配置了注解的類掃描到ioc容器里面,成為一個成熟的bean
 */
@Configuration
@ComponentScan(basePackages = {"com.lxl.www.iocbeanlifecicle"}) public class MainConfig { }

這個類有一個注解@Configuration, 這樣這個類會被掃描成bean

還有一個注解@ComponentScan(backPackage = {"com.lxl.www.iocbeanlifecicle"}) 他表示, 請掃描com.lxl.www.iocbeanlifecicle包下所有的類.

com.lxl.www.iocbeanlifecicle 這個包下還有哪些類呢? 我們來看看項目結構

 

 

 這是這個包下完整的項目結構. 

下面會逐漸說明, 每個類的用途

 

二. 最重要的類BeanFactory

我們知道在將一個class加載為bean的過程中BeanFactory是最最重要的, 那么他是何時被加載的呢?

我們來跟蹤一下帶有一個參數的構造方法AnnotationConfigApplicationContext

    public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
        // 進入構造函數, 首先調用自身的構造方法this();
        // 調用自身的構造方法之前, 要先調用父類的構造方法
        this(); // retister配置注冊類  register(componentClasses); // ioc容器shua新接口--非常重要  refresh(); }

這就是AnnotationConfigApplicationContext初始化的時候做的三件事

第一件事:  this();  //調用自身的無參構造方法. 同時調用父類的構造方法

第二件事: register(componentClasses); // 調用注冊器, 這里會加載兩個BeanDefinitionReader和BeanDefinitionScanner. 這兩位的角色是什么呢? 可以回憶一下之前的框架圖

第三件事: refresh();  // 這是ioc容器刷新, 非常重要. 無論是spring boot還是spring mvc都有這個方法. 這個方法包含了整個spring ioc加載的全生命流程. 也是我們要重點學習的方法

 

下面來看看BeanFactory是何時被加載進來的呢?

在初始化方法的時候調用了自身的無參構造函數, 在調用自身無參構造函數的時候, 同時會調用父類的無參構造函數. 

public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
  ......
}

父類是GenericApplicationContext, 其無參構造函數就做了一件事

   public GenericApplicationContext() {
        // 構造了一個BeanFactory.
        // 在調用GenericApplicationContext父類構造函數, 為ApplicationContext spring上下文對象初始化beanFactory
        // 為什么初始化的是DefaultListableBeanFactory呢?
        // 我們在看BeanFactory接口的時候發現DefaultListableBeanFactory是最底層的實現, 功能是最全的.
        // 查看
        this.beanFactory = new DefaultListableBeanFactory(); } 

初始化DefaultListableBeanFactory. 

問題: BeanFactory有很多, 為什么初始化的時候選擇DefaultListableBeanFactory呢?

我們來看看DefaultListableBeanFactory的結構. 快捷鍵option + command + u --> Java Class Diagrams

 

 

 通過觀察, 我們發現, DefaultListableBeanFactory實現了各種各樣的BeanFactory接口, 同時還是先了BeanDefinitionRegistry接口. 

也就是說, DefaultListableBeanFactory不僅僅有BeanFactory的能力, 同時還有BeanDefinitionRegistry的能力. 它的功能是最全的.

所以, 我們使用的是一個功能非常強大的類Bean工廠類. 

 

AnnotationConfigApplicationContext繼承了GenericApplicationContext,

而 GenericApplicationContext 實現了AnnotationConfigRegistry接口.

所以AnnotationConfigApplicationContext有AnnotationConfigRegistry的能力.

 

三. bean定義讀取器AnnotatedBeanDefinitionReader

接着上面, 第一步調用的是this(). 也就是AnnotationConfigApplicationContext的無參構造函數. 在這個無參構造函數里一共做了兩件事情

    public AnnotationConfigApplicationContext() {
        /**
         * 創建了一個Bean定義的讀取器.
         * 完成了spring內部BeanDefinition的注冊(主要是后置處理器)
         * 讀取了很多spring自定義的配置(主要是后置處理器). 這些類都是spring 的原始類.
         */
        this.reader = new AnnotatedBeanDefinitionReader(this); /**
         * 創建BeanDefinition掃描器
         * 可以用來掃描包或者類, 進而轉換為bd
         *
         * Spring默認的掃描包不是這個scanner對象
         * 而是自己new的一個ClassPathBeanDefinitionScanner
         * Spring在執行工程后置處理器ConfigurationClassPostProcessor時, 去掃描包時會new一個ClassPathBeanDefinitionScanner
         *
         * 這里的scanner僅僅是為了程序員可以手動調用AnnotationConfigApplicationContext對象的scan方法
         * 通過調用context.scan("package name");掃描處理配置類
         * 掃描
         */
        this.scanner = new ClassPathBeanDefinitionScanner(this); }

1. 初始化AnnotatedBeanDefinitionReader.

2. 初始化ClassPathBeanDefinitionScanner

我們先來看看AnnotatedBeanDefinitionReader

 

 

 在這里的描述中, 我們知道BeanDefinitionReader是要去掃描配置或者注解, 如果理解為銷售的話, 就是掃描樓盤. 這里面就有我們的潛在用戶. 也就是我們需要將其轉換為bean的對象. 

那么初始化的時候,AnnotatedBeanDefinitionReader做了什么呢?

重點看這句

    public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); Assert.notNull(environment, "Environment must not be null"); this.registry = registry; this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
     // 注冊注解類型配置的處理器 AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); }

注冊注解類型配置的處理器

AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);

   /**
     * Register all relevant annotation post processors in the given registry.
     * @param registry the registry to operate on
     * @param source the configuration source element (already extracted)
     * that this registration was triggered from. May be {@code null}.
     * @return a Set of BeanDefinitionHolders, containing all bean definitions
     * that have actually been registered by this call
     */
    public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
            BeanDefinitionRegistry registry, @Nullable Object source) {

        // 獲取到beanFactory
        DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry); /** * 判斷beanFactory中是否有AnnotationAwareOrderComparator和ContextAnnotationAutowireCandidateResolver * 沒有則添加 */ if (beanFactory != null) { if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) { beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); } if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) { beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); } } // BeanDefinitionHolder: 為BeanDefinition設置名字和別名 Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8); // 1. 如果registry中沒有ConfigurationClassPostProcessor配置類后置處理器, 就添加一個 if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class); def.setSource(source); // 構建BeanDefinitionHolder, 並添加到beanDefs  beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)); } // 2. 如果rigistry中, 沒有AutowiredAnnotationBeanPostProcessor Autowired注解bean的后置處理器, 則添加一個 if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class); def.setSource(source); // 構建BeanDefinitionHolder, 並添加到beanDefs  beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); } // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor. // 3. 檢查對JSR-250的支持, 如果rigistry中沒有CommonAnnotationBeanPostProcessor通用注解后置處理器, 則添加一個 if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class); def.setSource(source); // 構建BeanDefinitionHolder, 並添加到beanDefs  beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)); } // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor. // 4. 檢查對jpa的支持, 如果不包含internalPersistenceAnnotationProcessor, 持久化注解處理器, 就添加一個 if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(); try { def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, AnnotationConfigUtils.class.getClassLoader())); } catch (ClassNotFoundException ex) { throw new IllegalStateException( "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex); } def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)); } // 5. 檢查對事件監聽的支持, 如果不包含事件監聽處理器internalEventListenerProcessor, 就添加一個 if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME)); } // 6. 如果不包含事件監聽工廠處理器internalEventListenerFactory , 就添加一個 if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME)); } return beanDefs; }

在這里注冊了6個后置處理器.

 

 

 

四. bean定義掃描器ClassPathBeanDefinitionScanner

 

  public AnnotationConfigApplicationContext() {
        /**
         * 創建了一個Bean定義的讀取器.
         * 完成了spring內部BeanDefinition的注冊(主要是后置處理器)
         * 讀取了很多spring自定義的配置(主要是后置處理器). 這些類都是spring 的原始類.
         */
        this.reader = new AnnotatedBeanDefinitionReader(this); /** * 創建BeanDefinition掃描器 * 可以用來掃描包或者類, 進而轉換為bd * * Spring默認的掃描包不是這個scanner對象 * 而是自己new的一個ClassPathBeanDefinitionScanner * Spring在執行工程后置處理器ConfigurationClassPostProcessor時, 去掃描包時會new一個ClassPathBeanDefinitionScanner * * 這里的scanner僅僅是為了程序員可以手動調用AnnotationConfigApplicationContext對象的scan方法 * 通過調用context.scan("package name");掃描處理配置類 * 掃描 */ this.scanner = new ClassPathBeanDefinitionScanner(this); }

主要看加粗的部分. 這部分初始化了BeanDefinition掃描器. 這里的這個scanner不是spring默認的掃描包. Spring默認的掃描包不是這個scanner對象, 而是自己new的一個ClassPathBeanDefinitionScanner, Spring在執行后置處理器ConfigurationClassPostProcessor時, 去掃描包時會new一個ClassPathBeanDefinitionScanner, 這里的scanner僅僅是為了程序員可以手動調用AnnotationConfigApplicationContext對象的scan方法, 通過調用context.scan("package name");掃描處理配置類

 比如,我們可以這樣使用

    public static void main(String[] args) {
        // 第一步: 通過AnnotationConfigApplicationContext讀取一個配置類
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainStarter.class); context.scan("package name"); Car car = (Car) context.getBean("car"); System.out.println(car.getName()); context.close(); }

 

首先調用了ClassPathBeanDefinitionScanner(this) 構造方法, 然后調用registerDefaultFilter注冊摩爾恩的過濾器, 這里面默認的過濾器有兩種: javax.annotation.ManagedBean 和 javax.inject.Named. 同時隱含的會注冊所有帶有@Component @Repository @Controller關鍵字的注解

    @SuppressWarnings("unchecked")
    protected void registerDefaultFilters() { this.includeFilters.add(new AnnotationTypeFilter(Component.class)); ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader(); try { this.includeFilters.add(new AnnotationTypeFilter( ((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false)); logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning"); } catch (ClassNotFoundException ex) { // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.  } try { this.includeFilters.add(new AnnotationTypeFilter( ((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false)); logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning"); } catch (ClassNotFoundException ex) { // JSR-330 API not available - simply skip.  } }

 

在ClassPathBeanDefinitionScanner中, 有一個非常重要的方法, 就是doScan(String ....beanPackages). 用來掃描傳入的配置文件.

 

五.  注冊配置方法

    public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
        // 進入構造函數, 首先調用自身的構造方法this();
        // 調用自身的構造方法之前, 要先調用父類的構造方法
        this(); // register配置注冊類  register(componentClasses); // ioc容器shua新接口--非常重要  refresh(); }

這是AnnotationConfigApplicationContext方法的構造函數, 里面第二步調用了register()方法. 

 

 

 

  private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
            @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier, @Nullable BeanDefinitionCustomizer[] customizers) { // 將入參beanClass構建成AnnotatedGenericBeanDefinition對象 AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass); if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) { return; } abd.setInstanceSupplier(supplier); ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd); abd.setScope(scopeMetadata.getScopeName()); String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry)); // 處理通用定義注解  AnnotationConfigUtils.processCommonDefinitionAnnotations(abd); if (qualifiers != null) { for (Class<? extends Annotation> qualifier : qualifiers) { if (Primary.class == qualifier) { abd.setPrimary(true); } else if (Lazy.class == qualifier) { abd.setLazyInit(true); } else { abd.addQualifier(new AutowireCandidateQualifier(qualifier)); } } } if (customizers != null) { for (BeanDefinitionCustomizer customizer : customizers) { customizer.customize(abd); } } BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry); }

AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);用來加載bean元數據中的注解

BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);用來注冊bean定義. 經過一些列的教研, 沒有問題, 然后將其讓入到this.beanDefinitionMap.put(beanName, beanDefinition);中
具體做了哪些工作, 可以看看上面的結構圖

 六. Refresh() -- spring ioc容器刷新方法

    public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
        // 進入構造函數, 首先調用自身的構造方法this();
        // 調用自身的構造方法之前, 要先調用父類的構造方法
        this(); // register配置注冊類  register(componentClasses); // ioc容器shua新接口--非常重要  refresh(); }

refresh()方法, spring有很多衍生品, 比如spring mvc ,spring boot, 都有這個方法. refresh()里面定義了spring ioc中bean加載的全過程. 

    @Override
    public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // 1. 准備刷新上下文環境  prepareRefresh(); // Tell the subclass to refresh the internal bean factory. //2. 獲取告訴子類初始化bean工廠, 不同工廠不同實現 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. //3. 對bean工廠進行填充屬性  prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. // 4. 留個子類去實現該接口  postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. /* * 調用bean工廠的后置處理器 * 1. 會再次class掃描成BeanDefinition */ invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. // 注冊bean后置處理器  registerBeanPostProcessors(beanFactory); // Initialize message source for this context. // 初始化國際化資源處理器  initMessageSource(); // Initialize event multicaster for this context. // 創建事件多播放器  initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. // 這個方法通用也是留個子類實現的, spring boot也是從這個方法進行啟動  onRefresh(); // Check for listener beans and register them. // 將事件監聽器注冊到多播放器上  registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. // 實例化剩余的單實例bean /** * 這個方法就是循環遍歷BeanDefinitionMap, 調用getBean, 去生產bean */ finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. //最后容器刷新 發布刷新時間(spring cloud是從這里啟動的 )  finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // Destroy already created singletons to avoid dangling resources.  destroyBeans(); // Reset 'active' flag.  cancelRefresh(ex); // Propagate exception to caller. throw ex; } finally { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore...  resetCommonCaches(); } } }

這是refresh()的源碼, 在refresh()中做了很多很多事情, 我們這次主要看和ioc中beanFactory創建bean有關的部分.

 

一個是: invokeBeanFactoryPostProcessors(beanFactory);

另一個是: finishBeanFactoryInitialization(beanFactory);

 

6.1 invokeBeanFactoryPostProcessors(beanFactory) 調用BeanFactory的后置處理器

 在AnnotatedBeanDefinitionReader這里掃描了所有后置處理器, 將其解析到beanDefinitionMap, 在這里調用后置處理器

 

6.2 finishBeanFactoryInitialization 實例化剩余的單實例bean

 這個方法就是循環遍歷BeanDefinitionMap, 調用getBean, 去生產bean

 

這里第一個是: 凍結配置類, 意思是說, 我馬上就要開始制造bean了, bean配置文件不能再修改了, 所以被凍結

原理是有一個變量標記, 設為true標記凍結.

    @Override
    public void freezeConfiguration() { this.configurationFrozen = true; this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames); }

 

第二個是實例化創建bean

Override
    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { if (logger.isTraceEnabled()) { logger.trace("Creating instance of bean '" + beanName + "'"); } RootBeanDefinition mbdToUse = mbd; // Make sure bean class is actually resolved at this point, and // clone the bean definition in case of a dynamically resolved Class // which cannot be stored in the shared merged bean definition. // 確保此時的bean已經被解析了 Class<?> resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } // Prepare method overrides. try { /** * 驗證和准備覆蓋方法(近在xml方式中) * lookup-method 和 replace-method * 這兩個配置存放在BeanDefinition中的methodOverrides(僅在XML方式中) * 在XML方式中, bean實例化的過程中如果檢測到存在methodOverrides * 則會動態的為當前bean生成代理並使用對應的攔截器為bean做增強處理 * 具體的實現我們后續分析. 現在先看mbdtoUse.prepareMethodOverrides()代碼塊 */ mbdToUse.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", ex); } try { // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. /** * 初始化之前的解析 * 第一次調用bean后置處理器 * 銅鼓bean的后置處理器來進行后置處理生成代理對象, 一般情況下在此處不會生成代理對象 * 為什么不能生成代理對象? 不管是我們的JDK還是cglib代理都不會在此處進行代理, 因為我們的真實對象沒有生成, * 所以在這里不會生成代理對象 * 這一步是aop和事務的關鍵, 因為在這解析我們的aop切面信息進行緩存. */ Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } } catch (Throwable ex) { throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex); } try { /* * 執行創建bean, 這里就是執行創建bean的三個步驟 * 1. 實例化 * 2. 填充屬性, @Autowired @Value * 3. 初始化 初始化initMethod方法和初始化destroy方法 */ Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isTraceEnabled()) { logger.trace("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; } catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) { // A previously detected exception with proper bean creation context already, // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry. throw ex; } catch (Throwable ex) { throw new BeanCreationException( mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex); } }

 

創建bean的三個步驟 

 

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
            throws BeanCreationException {

        // Instantiate the bean.
        BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { /** * 第一步: 實例化 * 這里面的調用鏈非常深, 后面再看 * bean實例化有兩種方式 * 1. 使用反射: 使用反射也有兩種方式, * a. 通過無參構造函數 (默認的方式) * 從beanDefinition中可以得到beanClass, * ClassName = BeanDefinition.beanclass * Class clazz = Class.forName(ClassName); * clazz.newInstance(); * 這樣就可以實例化bean了 * * b. 通過有參函數. * ClassName = BeanDefinition.beanclass * Class clazz = Class.forName(ClassName); * Constractor con = class.getConstractor(args....) * con.newInstance(); * * 2. 使用工廠 * 我們使用@Bean的方式, 就是使用的工廠模式, 自己控制實例化過程 * */ instanceWrapper = createBeanInstance(beanName, mbd, args); } // 這里使用了裝飾器的設計模式 final Object bean = instanceWrapper.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } // Allow post-processors to modify the merged bean definition. // 允許后置處理器修改已經合並的beanDefinition  synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", ex); } mbd.postProcessed = true; } } // Eagerly cache singletons to be able to resolve circular references // even when triggered by lifecycle interfaces like BeanFactoryAware. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isTraceEnabled()) { logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // Initialize the bean instance. Object exposedObject = bean; try { // 第二步:填充屬性, 給屬性賦值(調用set方法) 這里也是調用的后置處理器  populateBean(beanName, mbd, instanceWrapper); // 第三步: 初始化. exposedObject = initializeBean(beanName, exposedObject, mbd); } catch (Throwable ex) { if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { throw (BeanCreationException) ex; } else { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); } } if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName, false); if (earlySingletonReference != null) { if (exposedObject == bean) { exposedObject = earlySingletonReference; } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length); for (String dependentBean : dependentBeans) { if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { actualDependentBeans.add(dependentBean); } } if (!actualDependentBeans.isEmpty()) { throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been " + "wrapped. This means that said other beans do not use the final version of the " + "bean. This is often the result of over-eager type matching - consider using " + "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example."); } } } } // Register bean as disposable. try { registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); } return exposedObject; }

 

具體結構如下:

 

 

 

我的博客即將同步至騰訊雲+社區,邀請大家一同入駐:https://cloud.tencent.com/developer/support-plan?invite_code=1gx5pavn3x1pz


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM