面试官:就问个Spring容器初始化和Bean对象的创建,你讲一小时了

前言

spring作为一个容器,可以管理对象的生命周期、对象与对象之间的依赖关系。可以通过配置文件,来定义对象,以及设置其与其他对象的依赖关系。

main测试类

 public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
        Bean bean = applicationContext.getBean(Bean.class);
        System.out.println(bean);
    }

ClassPathXmlApplicationContext类

  • application建立以后,可以通过refresh()进行重建,这样会将原来的application销毁,然后重新执行初始化

  • 构造方法

    public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
                throws BeansException {
    
            super(parent);
            //设置配置文件
            setConfigLocations(configLocations);
            if (refresh) {
                //核心方法
                refresh();
            }
        }
    
    

AbstractApplicationContext类

refresh方法

    @Override
    public void refresh() throws BeansException, IllegalStateException {
        // 同步,防止你在初始化的过程中被打断
        synchronized (this.startupShutdownMonitor) {
            // 准备工作
            prepareRefresh();

            // 配置文件被拆分成Bean定义,注册在BeanFactory中。
            // 也就是Map
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

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

            try {
                // 到这一步,所有的Bean加载和注册都已经完成,但是还没开始初始化
                // 如果实现了 BeanFactoryPostProcessor 接口,可以在初始化的时候做点事情
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                // 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 方法
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                // 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
                // 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
                // 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意,到这里 Bean 还没初始化
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                // 初始化当前 ApplicationContext 的 MessageSource, 国际化等
                initMessageSource();

                // Initialize event multicaster for this context.
                // 初始化当前 ApplicationContext 的事件广播器
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                // 从方法名就可以知道,典型的模板方法(钩子方法),
                // 具体的子类可以在这里初始化一些特殊的 Bean(在初始化 singleton beans 之前)
                onRefresh();

                // Check for listener beans and register them.
                // 注册监听,监听器需要实现 ApplicationListener 接口
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                // 初始化所有的singletons , non-lazy除外
                // 主要方法
                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();
            }
        }
    }

obtainFreshBeanFactory()方法

1、初始化 BeanFactory-》DefaultListableBeanFactory.class

DefaultListableBeanFactory beanFactory = createBeanFactory();

2、定义工厂的属性: 是否允许 Bean 覆盖、是否允许循环引用

3、加载 Bean 到 BeanFactory 中 -》 loadBeanDefinitions()方法

​ 3.1 读取xml配置文件,检查,解析

preProcessXml(root); //钩子
parseBeanDefinitions(root, this.delegate); //主要代码:将信息放在Factory的相关map中
postProcessXml(root); //钩子

​ 3.2 将xml配置文件的信息放到工厂的map里。

​ parseBeanDefinitions() => DefaultListableBeanFactory.class的registerBeanDefinition()方法

    this.beanDefinitionMap.put(beanName, beanDefinition);
    // beanName的集合,和Map的key(beanName)对应
    this.beanDefinitionNames.add(beanName);

具体不细讲,简述一下过程,就是factory有几个map,这里将xml里读出来的对象以Map的形式存储。
以及一个list保存了所有的beanName。

beanDefinition只是一个类的描述而已,和我们需要的对象还差了一大截。

4、返回携带各种信息的factory

finishBeanFactoryInitialization()方法

根据factory初始化所有的singletons , non-lazy除外

1、初始化特殊类,不展开啦。

2、缓存。还是DefaultListableBeanFactory.class。把之前我们上面讲到的带beanName的List转为数组保存到frozenBeanDefinitionNames里。

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

3、初始化。

​ 3.1 拿到带beanName的List,遍历循环

List beanNames = new ArrayList(this.beanDefinitionNames);

​ 3.2 特殊类FactoryBean等特殊处理,不展开了。

​ 3.3 进入对象实例化。

AbstractBeanFactory类的doGetBean()方法
AbstractAutowireCapableBeanFactory类的doCreateBean()

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

        ...
        if (instanceWrapper == null) {
            // 这里实例化 Bean,
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        ...
    }

AbstractAutowireCapableBeanFactory类的createBeanInstance()

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
        // Make sure bean class is actually resolved at this point.
        // 确保已经加载了此 class
        Class beanClass = resolveBeanClass(mbd, beanName);

        // 校验一下这个类的访问权限
        if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
        }

        if (mbd.getFactoryMethodName() != null) {
            // 采用工厂方法实例化,注意,不是 FactoryBean
            return instantiateUsingFactoryMethod(beanName, mbd, args);
        }

        // Shortcut when re-creating the same bean...
        // 如果不是第一次创建,比如第二次创建 prototype bean。
        // 这种情况下,我们可以从第一次创建知道,采用无参构造函数,还是构造函数依赖注入 来完成实例化
        boolean resolved = false;
        boolean autowireNecessary = false;
        if (args == null) {
            synchronized (mbd.constructorArgumentLock) {
                if (mbd.resolvedConstructorOrFactoryMethod != null) {
                    resolved = true;
                    autowireNecessary = mbd.constructorArgumentsResolved;
                }
            }
        }
        if (resolved) {
            if (autowireNecessary) {
                // 构造函数依赖注入
                return autowireConstructor(beanName, mbd, null, null);
            }
            else {
                // 无参构造函数
                return instantiateBean(beanName, mbd);
            }
        }

        // Candidate constructors for autowiring?
        // 判断是否采用有参构造函数
        Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
        if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
                mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
            // 构造函数依赖注入
            return autowireConstructor(beanName, mbd, ctors, args);
        }

        // No special handling: simply use no-arg constructor.
        // 调用无参构造函数
        return instantiateBean(beanName, mbd);
    }

AbstractAutowireCapableBeanFactory类的instantiateClass()

protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
        try {
            Object beanInstance;
            final BeanFactory parent = this;
            if (System.getSecurityManager() != null) {
                beanInstance = AccessController.doPrivileged(new PrivilegedAction() {
                    @Override
                    public Object run() {
                        return getInstantiationStrategy().instantiate(mbd, beanName, parent);
                    }
                }, getAccessControlContext());
            }
            else {
                // 实例化
                beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
            }
            // 包装一下,返回
            BeanWrapper bw = new BeanWrapperImpl(beanInstance);
            initBeanWrapper(bw);
            return bw;
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
        }
    }


public static  T instantiateClass(Constructor ctor, Object... args) throws BeanInstantiationException {
        Assert.notNull(ctor, "Constructor must not be null");
        try {
            ReflectionUtils.makeAccessible(ctor);
            return ctor.newInstance(args); //构造函数初始化对象
        }
        ...
}       

最后

感谢你看到这里,文章有什么不足还请指正,觉得文章对你有帮助的话记得给我点个赞,每天都会分享java相关技术文章或行业资讯,欢迎大家关注和转发文章!

你可能感兴趣的:(面试官:就问个Spring容器初始化和Bean对象的创建,你讲一小时了)