Spring IOC(1)----容器刷新(refresh())之前


首先本次分析是基於注解形式的,想來xml格式的原理都是類似的。

首先說一下什么是Bean定義(beandefinition):bean定義並不是實例化的bean,而是bean對象的一些信息,根據這些定義的信息最后來初始化bean。比方說就是一些類的信息,還有我們配置的該實例的信息(是否懶加載,單例還是多例,作用域等等信息)。

進入正題:

 

 

AnnotationConfigApplicationContext構造方法傳入一個主配置類,那么就從該構造方法進去。

 

 

一、我們先來看在容器刷新(refresh())之前,都干了什么

1.this()首先會調用無參構造,進而調用父類的無參構造,初始化beanFactory(DefaultListableBeanFactory),再者初始化注解模式下的bean定義讀取器,classPath類型的bean定義掃描器;

 

2.register(annotatedClasses),基於上面初始化的bean定義讀取器去解析注冊我們自己的配置類信息到容器中。

 

具體的流程圖如下:

 

 

 

完成了這些准備工作。refresh()里面就會實例化具體的bean了。

二、兩個個擴展點

1. BeanDefinitionRegistryPostProcessor

Bean定義處理器,在注冊bean定義的時候調用,可以自己注冊新的bean定義

先直接通過上下文對象獲取一個student,會報錯,沒有對應的bean定義

實現自己的Bean定義處理器

MyBeanDefinitionRegistryPostProcessor
package com.nijunyang.spring;

import com.nijunyang.spring.model.Student;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.stereotype.Component;

/**
 * @author: create by nijunyang
 * @date:2019/10/6
 */
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    //bean定義注冊處理器,在注冊bean定義的時候調用,可以自己注冊新的bean定義,比如Student
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        System.out.println("bean定義的數據量:"+registry.getBeanDefinitionCount());
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Student.class);
        //注冊一個名為student的bean定義進去
        registry.registerBeanDefinition("student", rootBeanDefinition);
        System.out.println("bean定義的數據量:"+registry.getBeanDefinitionCount());
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    }
}

 注意需要加上@Component,並且主配置指定掃描的包將自己定義的類加載進去

MainConfig
package com.nijunyang.spring;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * @author: create by nijunyang
 * @date:2019/10/6
 */
@Configuration
@ComponentScan(basePackages = "com.nijunyang.spring")
public class MainConfig {
}
 
        

 

 

 正常獲取bean。

 

2.BeanFactoryPostProcessor

BeanFactory后置處理器,注冊了bean定義之后調用,可以修改bean定義,比如實現一個自己的BeanFactory后置處理器,把某個bean設置成懶加載。

 斷點運行1步驟中的代碼,發現student不是懶加載的

 

 實現自己的BeanFactory后置處理器,將student設置成懶加載

MyBeanFactoryPostProcessor
package com.nijunyang.spring;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;

/**
 * @author: create by nijunyang
 * @date:2019/10/6
 */
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    //注冊了bean定義之后調用,可以修改bean定義,比如把student設置成懶加載
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        for(String name : beanFactory.getBeanDefinitionNames()) {
            if("student".equals(name)) {
                BeanDefinition beanDefinition = beanFactory.getBeanDefinition(name);
                beanDefinition.setLazyInit(true);
            }

        }
    }
}

 同樣斷點運行,發現student不會馬上被初始化了

 


免責聲明!

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



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