Spring容器初始化创建bean的流程分析

Spring框架提供的最重要特性之一就是IoC,让实例的创建与使用分离,开发者可以更好的专注于业务逻辑的处理。

Spring的发展从依赖xml配置文件到完全基于注解的SpringBoot,博主一直想搞明白spring是怎么管理bean实例的。下面主要基于注解的方式来学习,那么跟博主一起走一下吧!

SpringApplication.java

/**
 * Run the Spring application, creating and refreshing a new
 * {@link ApplicationContext}.
 * @param args the application arguments (usually passed from a Java main method)
 * @return a running {@link ApplicationContext}
 */
public ConfigurableApplicationContext run(String... args) {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    ConfigurableApplicationContext context = null;
    Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
    configureHeadlessProperty();
    SpringApplicationRunListeners listeners = getRunListeners(args);
    listeners.starting();   // 监听器启动
    try {
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);
        configureIgnoreBeanInfo(environment);
        Banner printedBanner = printBanner(environment);
        context = createApplicationContext();   // 创建应用上下文
        exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
        new Class[] { ConfigurableApplicationContext.class }, context);
        prepareContext(context, environment, listeners, applicationArguments,printedBanner);
        refreshContext(context);    // 重点:刷新上下文,参见AbstractApplicationContext.java
        afterRefresh(context, applicationArguments);
        stopWatch.stop();
        if (this.logStartupInfo) {
            new StartupInfoLogger(this.mainApplicationClass)
                .logStarted(getApplicationLog(), stopWatch);
        }
        listeners.started(context);
        callRunners(context, applicationArguments);
    }catch (Throwable ex) {
        handleRunFailure(context, ex, exceptionReporters, listeners);
        throw new IllegalStateException(ex);
    }
    try {
        listeners.running(context);
    }catch (Throwable ex) {
        handleRunFailure(context, ex, exceptionReporters, null);
        throw new IllegalStateException(ex);
    }
    return context;
}

/**
 * Strategy method used to create the {@link ApplicationContext}. By default this
 * method will respect any explicitly set application context or application context
 * class before falling back to a suitable default.
 * @return the application context (not yet refreshed)
 * @see #setApplicationContextClass(Class)
 */
protected ConfigurableApplicationContext createApplicationContext() {
    Class<?> contextClass = this.applicationContextClass;
    if (contextClass == null) {
        try {
            switch (this.webApplicationType) {  // webApplicationType为SERVLET
            case SERVLET:
                contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
                break;
            case REACTIVE:
                contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
                break;
            default:
                contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
            }
        }catch (ClassNotFoundException ex) 
            throw new IllegalStateException(
            "Unable create a default ApplicationContext, "+ "please specify an ApplicationContextClass",ex);
        }
    }
    return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);   // 实例化AnnotationConfigServletWebServerApplicationContext
}

public AnnotationConfigServletWebServerApplicationContext() {
    this.reader = new AnnotatedBeanDefinitionReader(this);
    this.scanner = new ClassPathBeanDefinitionScanner(this);
}
复制代码

图中蓝色线部分的继承体系中出现了最为重要的依赖beanFactory的context

/**
 * Create a new GenericApplicationContext.
 * @see #registerBeanDefinition
 * @see #refresh
 */
public GenericApplicationContext() {
    this.beanFactory = new DefaultListableBeanFactory();
}
复制代码

至此,context实例化完成,管理着BeanFactory的实现(DeafaultListableBeanFactory实例)

下面进行配置bean的实例化

AbstractApplicationContext.java

@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // Prepare this context for refreshing.
        prepareRefresh();

        // Tell the subclass to refresh the internal bean factory.
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // Prepare the bean factory for use in this context.
        prepareBeanFactory(beanFactory);

        try {
            // Allows post-processing of the bean factory in context subclasses.
            postProcessBeanFactory(beanFactory);

            // Invoke factory processors registered as beans in the context.
            invokeBeanFactoryPostProcessors(beanFactory); // 加载bean定义,存在beanFactory中

            // Register bean processors that intercept bean creation.
            registerBeanPostProcessors(beanFactory);

            // Initialize message source for this context.
            initMessageSource();
        
            // Initialize event multicaster for this context.
            initApplicationEventMulticaster();
        
            // Initialize other special beans in specific context subclasses.
            onRefresh();
        
            // Check for listener beans and register them.
            registerListeners();
        
            // Instantiate all remaining (non-lazy-init) singletons.
            // 根据bean定义,实例化所有非延迟初始化的单例(一般自定义的bean在此时创建)
            finishBeanFactoryInitialization(beanFactory);
        
            // Last step: publish corresponding event.
            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();
        }
    }
}

/**
 * Finish the initialization of this context's bean factory,
 * initializing all remaining singleton beans.
 */
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // Initialize conversion service for this context.
    if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
        beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
            beanFactory.setConversionService(beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
    }
    
    // Register a default embedded value resolver if no bean post-processor
    // (such as a PropertyPlaceholderConfigurer bean) registered any before:
    // at this point, primarily for resolution in annotation attribute values.
    if (!beanFactory.hasEmbeddedValueResolver()) {
        beanFactory.addEmbeddedValueResolver(strVal ->
            getEnvironment().resolvePlaceholders(strVal));
    }
    
    // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    for (String weaverAwareName : weaverAwareNames) {
        getBean(weaverAwareName);
    }
    
    // Stop using the temporary ClassLoader for type matching.
    beanFactory.setTempClassLoader(null);
    
    // Allow for caching all bean definition metadata, not expecting further changes.
    beanFactory.freezeConfiguration();
    
    // Instantiate all remaining (non-lazy-init) singletons.
    // 实例化所有非延迟单例bean
    beanFactory.preInstantiateSingletons();
}

@Override
public void preInstantiateSingletons() throws BeansException {
    if (logger.isTraceEnabled()) {
        logger.trace("Pre-instantiating singletons in " + this);
    }
    
    // Iterate over a copy to allow for init methods which in turn register new bean definitions.
    // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
    // beanFactory中所有的benaDef
    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
    
    // Trigger initialization of all non-lazy singleton beans...
    for (String beanName : beanNames) {
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            if (isFactoryBean(beanName)) {
                Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                    if (bean instanceof FactoryBean) {
                        final FactoryBean<?> factory = (FactoryBean<?>) bean;
                        boolean isEagerInit;
                        if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                            isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
                            ((SmartFactoryBean<?>) factory)::isEagerInit,
                            getAccessControlContext());
                        }else {
                            isEagerInit = (factory instanceof SmartFactoryBean &&((SmartFactoryBean<?>) factory).isEagerInit());
                        }
                        if (isEagerInit) {
                            getBean(beanName);
                        }
                    }
            }else {
                // spring中的bean创建大都是通过getBean来触发
                getBean(beanName);
            }
        }
    }
    
    // Trigger post-initialization callback for all applicable beans...
    for (String beanName : beanNames) {
        Object singletonInstance = getSingleton(beanName);
        if (singletonInstance instanceof SmartInitializingSingleton) {
            final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged((PrivilegedAction<Object>)
                    () -> {
                        smartSingleton.afterSingletonsInstantiated();
                        return null;
                    }, getAccessControlContext());
            }else {
                smartSingleton.afterSingletonsInstantiated();
            }
        }
    }
}

AbstrctBeanFactory.java
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
	// 省略部分代码
	
	if (mbd.isSingleton()) {
	    // 获取单例
	    sharedInstance = getSingleton(beanName, () -> {
	        try {
	            return createBean(beanName, mbd, args);
	        }catch (BeansException ex) {
	        // Explicitly remove instance from singleton cache: It might have been put there
	        // eagerly by the creation process, to allow for circular reference resolution.
	        // Also remove any beans that received a temporary reference to the bean.
	            destroySingleton(beanName);
	            throw ex;
	        }});
	        bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
	}
}

DefaultSingletonBeanRegistry.java
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory){
    synchronized (this.singletonObjects) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null) {
            // 省略部分代码
            
            singletonObject = singletonFactory.getObject();//此处singletonFactory是lambda表达式的内部类调用creatBean(args...)
            
            // 省略部分代码
            if (newSingleton) {
                addSingleton(beanName, singletonObject);
            }
        }
    }
}

DefaultSingletonBeanRegistery.java
protected void addSingleton(String beanName, Object singletonObject) {
    synchronized (this.singletonObjects) {
        // 加入singletonObejects Map集合
        this.singletonObjects.put(beanName, singletonObject);
        this.singletonFactories.remove(beanName);
        this.earlySingletonObjects.remove(beanName);
        this.registeredSingletons.add(beanName);
    }
}
复制代码

其中lambda表达式最终调用的是DefaultListableBeanFactory的父类AbstractAutowireCapableBeanFactory.java

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {
    // 省略部分代码

    Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    
    //省略部分代码
}

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)throws BeanCreationException {
    // 省略部分代码
    
    instanceWrapper = createBeanInstance(beanName, mbd, args);
    
    //省略部分代码
}

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    //省略部分代码
    
    return instantiateUsingFactoryMethod(beanName, mbd, args);
    
    // 省略部分代码
}

protected BeanWrapper instantiateUsingFactoryMethod(String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
    return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
}

ConstructorResolver.java
public BeanWrapper instantiateUsingFactoryMethod(String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
    //省略部分代码
    
    bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));
    //省略部分代码
}

private Object instantiate(String beanName, RootBeanDefinition mbd,@Nullable Object factoryBean, Method factoryMethod, Object[] args) {
    //省略部分代码
    
    return this.beanFactory.getInstantiationStrategy().instantiate(mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args);
}

SimpleInstantiationStrategy.java
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,@Nullable Object factoryBean, final Method factoryMethod, Object... args) {
    // @Configuration注解的类,利用反射执行里面的方法创建bean
    // 此处的factoryMethod就是带有@Bean注解的方法
    Object result = factoryMethod.invoke(factoryBean, args);
    if (result == null) {
        result = new NullBean();
    }
    return result;
}
复制代码

而后创建好的bean实例,放入beanFactory管理的一个Map

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值