Spring源码深度解析系列一:IOC容器源码

前言

IOC容器说简单点,其实就是一个Map singletonObjects,创建IOC容器的时候就往容器中添加这样的键值对,需要的时候就去容器中取即可。

由于Spring推荐使用注解的方式来使用IOC容器,并且之后学习SpringBoot也是支持全注解,零XML配置。因此本文将全程使用注解来讲解。

IOC源码中涉及到的容器类比较多,我们可以将他们分成2类,如下图,一个是BeanFactory,另一个是ApplicationContext。由这两个接口延伸出子类xxxBeanFactory,xxxApplicationContext。由下图可以明显看出分成了两个体系。Spring源码深度解析系列一:IOC容器源码_第1张图片
BeanFactory接口代表的是最基础的容器类,定义了容器的最基本行为(方法):getBean()、containsBean()等获取bean、判断bean是否存在的方法。ApplicationContext也是容器类,它也是继承自BeanFactory接口,不过它还继承了MessageSource(国际化信息)、ApplicationEventPublisher(事件发布机制)等接口,因此它就有了一些别的特性,称为高级容器。

Spring源码中随处可见模板模式,即由一个AbstracXXX类来实现一系列接口,并且实现一些公共方法,但是保留一些扩展接口供子类来实现。我们可以将上图简化一下,得到下图。明显的2个体系已经划分出来了,那么这两个体系有什么关系呢?答案是聚合关系,高级容器GenericApplicationContext中持有普通容器DefaultListableBeanFactory,那么以后跟bean相关的操作都是在DefaultListableBeanFactory中进行的。
Spring源码深度解析系列一:IOC容器源码_第2张图片

正文

一、IOC能做什么?是怎么做的?
IOC可以为用户创建,管理bean实例。用户需要bean实例对象时只需要从IOC容器中获取就行了,不需要自己去new,从而达到与具体类解耦的效果。

IOC的实现步骤是:1.用户配置bean定义;2.IOC容器加载bean定义;3.IOC容器创建bean实例;4.用户从IOC容器获取bean定义。

使用注解的方式配置如下:
1.首先定义一个普通的bean,加上@Component注解,表示这是一个组件。

package org.study.jimmy.bean;
import org.springframework.stereotype.Component;

@Component
public class Apple {
    private String name;
}

2.然后定义一个配置类,这个配置类上有2个注解,一个@Configuration,表示这是一个注解类。另一个是@ComponentScan,指定容器包扫描的路径。

package org.study.jimmy.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("org.study.jimmy.bean")
public class Config {

}

3.最后在main方法中启动容器,在从容器中获取bean实例。

package org.study.jimmy;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.study.jimmy.bean.Apple;
import org.study.jimmy.config.Config;

public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
        Apple apple = context.getBean(Apple.class);
    }
}

以上就是IOC容器注解配置的最基本使用方式。

二、源码追踪
我们在上面的main方法中的容器初始化方法那一行打上断点,追踪进代码看看。

	public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
		this();
		register(componentClasses);
		refresh();
	}

你可能感兴趣的:(spring源码)