玩转Spring 之 IOC容器

Spring 理念之 IOC

提到Spring,我们应该印象最深刻的就是IOC (Inversion of Control),即控制反转

关于IOC,其实是一种设计理念,只是Spring将这个理念体现的淋漓尽致,所以一说到Spring,我们固然会很快的联想到IOC。IOC还有另外一个名字叫DI (Dependency Injection)依赖注入,其实,准确的来说,IOC是理念,那DI就是IOC的实现

关于IOC更多详细理解可以看看这篇文章,IoC 之 2.1 IoC基础 ——跟我学Spring3

只要用过Spring,应该对Spring容器都不会陌生,这也是实现IOC的基础。在Spring中,我们所有的Bean实例都是交由Spring管理,包括Bean的实例化,初始化及销毁。Spring容器在启动时,会去扫描所有需要实例化的Bean,然后帮助我们去实例化,并且会自动将依赖的Bean同时实例化然后赋值,整个过程,我们完全不需要关心,而且Spring还提供了一系列用于我们自定义扩展的接口,如InitializingBeanFactoryBeanApplicationContextAwareBeanPostProcessor等等。

Spring 容器介绍

关于Spring容器,我们可以重点关注两个接口:

  • BeanFactory
    这是最顶层的Spring容器的,它只定义了Spring容器的规范,更多的是面向Spring内部,一般我们不会直接去使用BeanFactory
    在查看Spring源码的过程中就会发现,BeanFactory有很多的子接口以及实现类,最典型的如:DefaultListableBeanFactory,该实现类一直贯穿着Spring容器的启动流程。

DefaultListableBeanFactory 继承关系如下:


从上图我们可以看出,DefaultListableBeanFactory最终实现的最顶层的接口就是BeanFactory,而BeanFactory只定义了诸如BeanFactory#getBean()等接口方法,所以Spring通过子接口以及抽象实现类的方式可以提供更全面的功能,如AbstractBeanFactory#createBean用于创建实例化的Bean。

  • ApplicationContext
    ApplicationContext其实也是Spring的容器,从字面意思可以理解为应用的上下文,也可以说是对BeanFactory的扩展,因为ApplicationContext不仅拥有BeanFactory的基本功能外,还提供了更多入口让我们接入Spring。ApplicationContext还管理着Spring容器的生命周期,如容器的启动和关闭,并且还提供了更丰富的功能如事件发布监听,国际化等。

这里我们重点看一下GenericApplicationContext,继承关系图如下:

在这里插入图片描述
GenericApplicationContext中会发现它持有一个DefaultListableBeanFactory的引用,在Spring容器的启动流程中,就是利用DefaultListableBeanFactory引入BeanFactory中的所有功能。

Spring 容器启动

关于Spring容器的启动流程,其实大致包括以下几个步骤:

  1. 实例化BeanFactory,因为这是容器的基础,Spring中离不开BeanFactory
  2. BeanFactory做一些初始化,如添加一些默认的组件。
  3. 读取以及解析我们的配置类或者配置文件,然后将读取到的Bean封装到BeanDefinition缓存在一个beanDefinitionMap中。
  4. 对解析到的BeanDefition进行实例化。
  5. 在实例化Bean的时候会执行Bean属性的填充,如依赖注入,然后做一些初始化,在初始化前后会执行Bean的拦截器。

了解完大致步骤,再从源码的角度去验证上面这些步骤,这里我使用的Java注解配置的,所以就从AnnotationConfigApplicationContext开始:

实例化Spring容器,AnnotationConfigApplicationContext

AnnotationConfigApplicationContext的构造方法中,整个过程可以分为三步进行:
AnnotationConfigApplicationContext构造方法

  1. 实例化BeanFactory
    从上面的类继承关系图可以看出,AnnotationConfigApplicationContext间接继承了GenericApplicationContext,所以最终会调用父类的构造方法:
    GenericApplicationContext构造中实例化BeanFactory

    GenericApplicationContext的构造方法中直接new 了一个DefaultListableBeanFactory

  2. 注册基础的BeanPostProcessor
    AnnotationConfigApplicationContext的无参构造中会去创建AnnotatedBeanDefinitionReader
    AnnotationConfigApplicationContext无参构造

    由于AnnotationConfigApplicationContext继承自GenericApplicationContext,而GenericApplicationContext又实现了BeanDefinitionRegistry,这样就拥有了注册BeanDefinition的能力,所以在AnnotatedBeanDefinitionReader实例化的时候会去注册一些基础的BeanFactoryPostProcessorBeanPostPorcessor

    public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
    		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    		Assert.notNull(environment, "Environment must not be null");
    		this.registry = registry;
    		this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
    		// 注册基础的BeanFactoryPostProcessor和BeanPostPorcessor
    		AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    	}
    

    此处具体的注册组件有:

    public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
    		BeanDefinitionRegistry registry, @Nullable Object source) {
    	// 将BeanDefinitionRegistry转换为DefaultListableBeanFactory 
    	DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
    	if (beanFactory != null) {
    		// 注解的排序
    		if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
    			beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
    		}
    		// @Autowired 的解析器
    		if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
    			beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
    		}
    	}
    
    	Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
    	// 注册ConfigurationClassPostProcessor,用于后续解析配置类
    	if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
    		RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
    		def.setSource(source);
    		beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
    	}
    	// 注册AutowiredAnnotationBeanPostProcessor,用于Bean实例化后的依赖注入
    	if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
    		RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
    		def.setSource(source);
    		beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    	}
    	// 注册CommonAnnotationBeanPostProcessor,用于@Resource注解的依赖注入
    	// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
    	if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
    		RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
    		def.setSource(source);
    		beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
    	}
    	
    	......
    	// 注册JPA的BeanPostProcessor
    	// 注册EventListenerMethodProcessor
    	// 注册DefaultEventListenerFactory
    	return beanDefs;
    }	
    
  3. 手工注册配置类
    由于AnnotationConfigApplicationContext注册Bean定义信息的能力,所以最终将当前我们指定的配置类注册到容器中:

	registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
容器启动

AbstractApplicationContext#refresh是Spring容器启动的核心方法,该方法从整体上定义了Spring容器启动的整个流程,无论是SpringMVC,又或者Sping-boot,最终都会执行该方法去启动Spring容器:

public void refresh() throws BeansException, IllegalStateException {
		...... 
        // 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);

        // 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();
        ......
    }

按顺序查看每个方法的作用,大致如下:

  1. prepareRefresh():容器刷新前的准备,如设置当前已经容器已经激活this.active.set(true)
  2. obtainFreshBeanFactory():获取当前上下文的BeanFactory实例,检查当前的refresh()方法是否只被执行了一次,设置BeanFactory的serializationId。
  3. prepareBeanFactory(beanFactory):获取ClassLoader,设置基础的BeanPostProcessor如:ApplicationContextAwareProcessor,设置StandardBeanExpressionResolverSpring EL表达式的解析器。设置某些接口的实现类不需要交由容器去实例化,如ApplicationContext,因为ApplicationContext在Spring启动时(第一步中)已经实例化完成不需要参与后续的Bean实例化过程。
  4. postProcessBeanFactory(beanFactory)AbstractApplicationContext中定义的模板方法,可以重写实现注册一些额外的BeanPostProcessor。
  5. invokeBeanFactoryPostProcessors(beanFactory):执行BeanFactoryPostProcessor,用于解析@Configuration的配置类,如:扫描需要加载的Bean(@ComponentScan),通过@Import以及通过实现ImportBeanDefinitionRegistrar加载对应的BeanDefinition等。
  6. registerBeanPostProcessors(beanFactory):按照优先级去注册BeanPostProcessor,通过调用AbstractBeanFactory#getBean创建所有的BeanPostProcessor的实例并缓存在BeanFactory中,用于后续实例化其他Bean的时候做一些拦截处理,如:AOP生成代理对象。
  7. initMessageSource():初始化用于国际化的组件,这里不重点研究。
  8. initApplicationEventMulticaster():用于初始化Spring 事件的处理器。
  9. onRefresh():模板方法,用于子类实现。
  10. registerListeners() :注册监听器。
  11. finishBeanFactoryInitialization(beanFactory)这是重点方法,开始实例化所有的单例Bean实例。
  12. 容器刷新完毕后处理。
具体的执行源码由于篇幅原因拆分为多篇文章,可以按照下方的顺序:
  1. BeanFactory的实例化obtainFreshBeanFactory():不同配置方式的BeanFactory实例化。
  2. BeanFactory的准备:prepareBeanFactory(beanFactory):钩子方法的具体实现。
  3. 配置类的解析,invokeBeanFactoryPostProcessors(beanFactory)手把手玩转 Spring 之 配置类解析ConfigurationClassPostProcessor
  4. FactoryBean的创建 finishBeanFactoryInitialization(beanFactory)手把手玩转 Spring 之 FactoryBean的创建
  5. 单例Bean的创建
  6. 单例Bean的初始化
  7. 基于Aware 接口的扩展:手把手玩转Spring 之 ApplicationContextAware
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值