Spring什么时候实例化Bean的?

今天忽然想到一个问题,Spring是什么时候实例化Bean的?

1、是spring容器启动的时候?

2、还是第一次用到bean的时候实例化?

于是决定看一下源码

N年以前,spring还没有现在这么强大的时候,我们是如何使用spring的呢?使用XML文件配置,如下:

public class SchoolServiceImpl {

    public String getTimeStr(){
      return   LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:MM:ss"));
    }

    public String getInStr(String str){
        return str;
    }
}
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="schoolService" class="com.learn.spring.spring01.service.SchoolServiceImpl">

    </bean>
</beans>

将SchoolServiceImpl注册进spring,让spring管理。这步是怎么完成的呢?入下:

public static void main(String[] args) {
		
		ApplicationContext context = new ClassPathXmlApplicationContext("schoolService.xml");

		SchoolServiceImpl service = context.getBean("schoolService", SchoolServiceImpl.class);

		System.out.println(service.getTimeStr());
	}

开始debug

主要步骤:

1、创建beanFactory的实例DefaultListableBeanFactory,这个对象管理所有bean,为什么说它管理着所有bean对象呢,下面会说到

refresh()->obtainFreshBeanFactory->refreshBeanFactory->DefaultListableBeanFactory beanFactory = this.createBeanFactory();

2、根据路径读取XML文件、并解析xml文件,注册bean

loadBeanDefinitions(beanFactory)->新建XmlBeanDefinitionReader对象,负责xml的读取->loadBeanDefinitions(beanDefinitionReader)->loadBeanDefinitions(configLocations),根据上面代码中指定的XML文件位置,去相应读取,如果是多个xml文件,则是循环解析->XmlBeanDefinitionReader中进一步处理,将读到的Resource对象进一步解析->doLoadBeanDefinitions方法完成两件事,将xml解析为Document对象,注册bean->DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions.parseBeanDefinitions的方法解析xml每个bean标签、import标签等,其中的parseDefaultElement如下:
 

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
        if (delegate.nodeNameEquals(ele, "import")) {
            this.importBeanDefinitionResource(ele);
        } else if (delegate.nodeNameEquals(ele, "alias")) {
            this.processAliasRegistration(ele);
        } else if (delegate.nodeNameEquals(ele, "bean")) {
            this.processBeanDefinition(ele, delegate);
        } else if (delegate.nodeNameEquals(ele, "beans")) {
            this.doRegisterBeanDefinitions(ele);
        }

    }

->processBeanDefinition方法将每个bean标签解析为BeanDefinitionHolder对象,这个对象里面已经包含了bean的抽象定义BeanDefinition对象,这个对象比较关键,它包含的这个bean是单例还是多例、是不是懒加载等信息。因为以后的bean的实例化都是在这里拿到BeanDefinition对象,去实例化的。registerBeanDefinition注册->DefaultListableBeanFactory下的registerBeanDefinition方法会判断当前是否已经存在了该bean的BeanDefinition对象,判断的依据就是beanDefinitionMap能不能找到,如果没有,则把这个beanName和BeanDefinition放到这个map中、和beanDefinitionNames这个list中

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
    @Nullable
    private static Class<?> javaxInjectProviderClass;
    private static final Map<String, Reference<DefaultListableBeanFactory>> serializableFactories;
    @Nullable
    private String serializationId;
    private boolean allowBeanDefinitionOverriding = true;
    private boolean allowEagerClassLoading = true;
    @Nullable
    private Comparator<Object> dependencyComparator;
    private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver();
    private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap(16);
// 放到这个map里缓存起来
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256);
    private final Map<String, BeanDefinitionHolder> mergedBeanDefinitionHolders = new ConcurrentHashMap(256);
    private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap(64);
    private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap(64);
    private volatile List<String> beanDefinitionNames = new ArrayList(256);
    private volatile Set<String> manualSingletonNames = new LinkedHashSet(16);
    @Nullable
    private volatile String[] frozenBeanDefinitionNames;
    private volatile boolean configurationFrozen = false;

可以看到,每一个bean注册完成之后,对应的BeanDefinition都会放到DefaultListableBeanFactory中的beanDefinitonMap中,所以可以说这个beanFactory的对象管理着所有bean

3、创建、填充bean属性、实例化Bean

实例化一个对象的基本过程是:

// 1、创建SchoolEntity类的实例,entity对象
SchoolEntity entity = new SchoolEntity();

// 2、给entity对象填充属性
entity.setName("jack");
entity.setAge(12);

// 3、使用entity对象做一些事情
Use entity...

System.out.println(entity.getName);

spring里的流程如下:

在第一步的obtainFreshBeanFactory方法执行完毕之后,最终会执行finishBeanFactoryInitialization(beanFactory)->preInstantiateSingletons->this.getBean(这一步会取出beanDefinitionNames中所有beanName进行循环获取bean

)->doGetBean->this.getSingleton(beanName),此时这个bean还不存在,则创建这个bean->

this.createBean->this.doCreateBean->创建好bean之后,将这个bean放到DefaultSingletonBeanRegistry的singletonObjects这个map中

try {
                    singletonObject = singletonFactory.getObject();
                    newSingleton = true;
                } catch (IllegalStateException var16) {
                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        throw var16;
                    }
                } catch (BeanCreationException var17) {
                    BeanCreationException ex = var17;
                    if (recordSuppressedExceptions) {
                        Iterator var8 = this.suppressedExceptions.iterator();

                        while(var8.hasNext()) {
                            Exception suppressedException = (Exception)var8.next();
                            ex.addRelatedCause(suppressedException);
                        }
                    }

                    throw ex;
                } finally {
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = null;
                    }

                    this.afterSingletonCreation(beanName);
                }
// 添加进map中
                if (newSingleton) {
                    this.addSingleton(beanName, singletonObject);
                }

this.doCreateBean(创建bean对象)->this.populateBean(填充bean的属性)->this.initializeBean实例化bean。

其实以上步骤,官方文档都已经给出了很简洁有力的文档,并且官方建议要尽早的注册。

官方文档

对于单例,如果没有配置lazy-init,那么spring容器启动的时候,就会提前创建,而对于多例,则是用到的时候才创建

官方文档

UsefulLink:

1. Spring官方文档

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值