Spring Ioc容器启动和Bean装配

Spring框架主要解决Bean的自动生成和依赖注入问题,通过Ioc容器管理Bean的生命周期。在容器初始化时,涉及BeanDefinition、BeanFactoryPostProcessor和BeanPostProcessor等概念。Bean装配过程中,包括反射创建Bean、依赖注入、三级缓存处理循环依赖等。文章通过分析`refresh()`方法展示了Spring如何启动和初始化上下文。
摘要由CSDN通过智能技术生成

Spring框架是我接触的第一个框架,那时候觉得像天书一样复杂,但因为java开发者很多,所以相关的Spring 框架解析视频,博客是非常多的,而且讲得细致又清晰。而到面试的时候,Spring 也几乎是基础必问的题目,很多时候我有印象,但脑海中又没有很清晰的概念,所以我得再学习一遍,并用博客的形式做个记录。

很多时候,理解一个框架得知道这个框架是做什么的,它解决了什么问题,然后会用,再跟踪代码debug一下它的内部执行流程,知道它怎么做,跳出来,然后才知道它是通过什么样的方式解决一个问题的。当然,Spring 框架的代码量很大,我们只需要知道它的重要步骤和关键节点就可以了。但像Spring 事务这种代码量不算大的框架,应该会有人手写一个事务管理器的。

Spring 框架主要解决Bean的自动生成和Bean的注入和依赖问题,因为Spring有一个装满了Bean的Ioc容器,在这个容器里的所有Bean都是由Ioc容器所管理的,这些Bean的内部依赖也被Ioc容器所解决了。所以Spring有两个问题要解决:1是容器初始化,因为容器是管理Bean的生命周期的,是为Bean服务的,所以容器初始化的一切步骤都是为了创建Bean的环境而服务,包括解析bean标签创建BeanDefinition,BeanDefinition是Bean实例化和初始化的基础;创建BeanFactoryPostProcessor类,这个类可以修改BeanDefinition的信息;注册BeanPostProcessor,它可以拦截所有Bean的创建和初始化,给所有Bean添加一些统一的东西;还有一些MessageSource支持国际化,事件广播机制的初始化,但我们用得很少,不是主要的内容。 2是Bean的装配,Bean会在BeanDefinition的基础上通过new 或反射的方式创建出来,并解决Bean内部引用的依赖注入问题,然后被BeanPostProcessor所拦截并进一步初始化,添加一些信息,在这个过程中,Bean会通过三级缓存的方式解决循环依赖的问题,如果要生成Bean的代理,会涉及到Spring Aop。在Bean装配的过程中,还有InitialingBean这种接口的afterPropertiesSet()这种初始化的钩子方法,还有bean标签的init-method 属性的钩子方法,在容器完全初始化完后还有@PostConstruct这样的钩子方法。

所以我们很明显地看到Spring 框架就做了这两件事,这两件事是有联系的,Spring只想做第二件事,但做第二件事前得先做第一件事,先创建Ioc容器,再往Ioc里填充Bean,后面我们只需要往Ioc容器里拿Bean来用就可以了。

首先我们先写一个demo。

    public void testApp() {
        ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
        TestService testService = (TestService) context.getBean("testService");
        String result = testService.hello("world");
        System.out.println(result);
    }

new ClassPathXmlApplicationContext()会创建Ioc容器并完成Bean的装配,如果这个过程中出现了问题,就启动失败,直接报错。后面我3句代码是检查这个容器里是否有名称为testService的Bean对象,有就取出来,执行它的一个方法。

查看ClassPathXmlApplicationContext类及其父类,父类的父类,没多久就看到了 AbstractApplicationContext#refresh()方法。

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);
                // 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.
                finishBeanFactoryInitialization(beanFactory);
                // Last step: publish corresponding event.
                finishRefresh();
            }
            catch (BeansException ex) {
                ...
            }
            finally {
                // Reset common introspection caches in Spring's core, since we
                // might not ever need metadata for singleton beans anymore...
                resetCommonCaches();
            }
        }
    }

这里使用了模板模式来完成初始化,如果是web 项目,还会初始化web子容器。 网上找的图:

每一个方法都会做很多事情。

未完待续。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值