Spring之IOC



简介

Spring框架中最为核心的就是IOC和AOP,本文重点讲解IOC,本文很长,做好途中关闭页面的准备:)

什么是Inversion of Control(IOC)

在现实模型中大部分高层建筑都是需要依赖于底层建筑的。

依赖无倒置:在软件设计里,遵循现实模型,高层模块依赖底层,即底层是接口,高层是实现。依赖无倒置会造成高层模块频繁改动,违背开放封闭原则。

依赖倒置(DIP):在软件设计里,底层模块依赖高层,即高层是接口,底层是实现。 反转控制(IOC):DIP只是一个原则,而IOC是DIP的设计模式。支持IOC框架有Spring等。 依赖注入(DI):是IOC的一种功能,将依赖对象(底层)的创建和绑定转移到被依赖对象(高层)类的外部来实现。

通过IOC容器可以解耦高层和底层模块。

Spring的IOC功能

  1. 提供Bean的详细生命周期接口以及部分实现;
  2. 解析Bean相关资源;
  3. 把Bean信息加载到工厂容器里面;
  4. 初始化Bean;
  5. 解决Bean的依赖注入;
  6. 提供IOC容器的上下文给应用。

其中步骤1对于应用角度而言是非常重要的,需要开发者了解Spring的生命周期,步骤4和5有可能递归,是IOC的核心。


Spring的IOC层次分析

在这里默认读者都会使用Spring的开发注解方式。

Spring的源码非常庞大,在阅读源码之前,一定要有分层的思想,IOC涉及到的主要模块分别是:

core我不分析,aop在后续会分析,现在重点分析beans和context。

Context

先分析我们开发者最熟悉的context,以AnnotationConfigApplicationContext为例,以下是类层次图:

AnnotationConfigApplicationContext层次图

其中黄色边框是core包的接口/类,蓝色边框的是beans包的接口/类,其余都是context包的接口/类。

core这里代表是底层代码,不分析。

beans包的接口:

AnnotationConfigApplicationContext实现beans的接口是为了上下文可以调用getBean等方法。

context包的接口:

spring通过分层,只耦合了少部分beans包的代码,并通过内部变量引用BeanFactory,屏蔽了开发者对BeanFactory访问权。

Beans

对DefaultListableBeanFactory分析,以下是类层次图:

DefaultListableBeanFactory层次图

其中黄色边框是core包的接口/类,其余都是beans包的接口/类。

core这里代表是为了管理别名资源,不分析。

beans的接口:

DefaultListableBeanFactory的主要作用是为了解决自动注入和为context提供BeanFactory内的bean信息,Bean信息均在字段DefaultListableBeanFactory.beanDefinitionMap。

Spring的IOC相关注解

如今Spring基本是利用注解开发的,特别从Spring Boot开始后,我只列出开发中比较常用的注解。

资源相关

依赖相关

生命周期相关

Spring的IOC生命周期相关接口

LifeCycle接口

普通Bean

PostProcessor

有点像责任链,也是可以排序且不断调用后面的任务,类似拦截普通Bean。

在BeanFactory外的操作都在Beans包外,可见Spring源码分层还是很明显的,值得我们学习。

测试生命周期代码

以下是测试的代码,包含了IOC的生命周期、Factory的处理和循环依赖等功能,可以利用断点进行Debug。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
public class IocTests {

    @Test
    public void testLifeCycle() {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
                LifeCycleConfig.class,
                TestBeanPostProcessor.class,
                TestBeanFactoryPostProcessor.class);
        System.out.println("========================================================");
        ctx.registerShutdownHook();
    }
}

@Configuration
class LifeCycleConfig {

    @Bean(autowire = Autowire.BY_TYPE)
    TestBean testBean() {
        System.out.println("testBean constructor");
        return new TestBean();
    }

    @Bean
    InjectedBean injectedBean() {
        System.out.println("injectedBean constructor");
        return new InjectedBean();
    }

    @Bean
    BeanA beanA() {
        System.out.println("beanA constructor");
        return new BeanA();
    }

    @Bean
    BeanB beanB() {
        System.out.println("beanB constructor");
        return new BeanB();
    }

    class TestBean implements InitializingBean,
            DisposableBean,
            BeanFactoryAware,
            ApplicationListener<ApplicationEvent> {

        private InjectedBean injectedBean;

        @PostConstruct
        public void customInit() {
            System.out.println("testBean customInit");
        }

        @PreDestroy
        public void customDestroy() {
            System.out.println("testBean customDestroy");
        }

        @Override
        public void destroy() throws Exception {
            System.out.println("testBean destroy");
        }

        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("testBean afterPropertiesSet");
        }

        public InjectedBean getInjectedBean() {
            return injectedBean;
        }

        public void setInjectedBean(InjectedBean injectedBean) {
            this.injectedBean = injectedBean;
        }

        @Override
        public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
            System.out.println("testBean setBeanFactory " + beanFactory.getClass().getSimpleName());
        }


        @Override
        public void onApplicationEvent(ApplicationEvent event) {
            System.out.println("testBean " + event.getClass().getSimpleName());
        }
    }

    class InjectedBean {
    }

    class BeanA {
        private BeanB beanB;

        public BeanB getBeanB() {
            return beanB;
        }

        @Autowired
        public void setBeanB(BeanB beanB) {
            this.beanB = beanB;
        }
    }

    class BeanB {
        private BeanA beanA;

        public BeanA getBeanA() {
            return beanA;
        }

        @Autowired
        public void setBeanA(BeanA beanA) {
            this.beanA = beanA;
        }
    }
}

@Component
class TestBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if ("testBean".equals(beanName)) {
            System.out.println("testBean postProcessBeforeInstantiation");
        }
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if ("testBean".equals(beanName)) {
            System.out.println("testBean postProcessAfterInstantiation");
        }
        return true;
    }

    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
        if ("testBean".equals(beanName)) {
            Arrays.stream(pvs.getPropertyValues()).forEach(p ->
                    System.out.println("testBean postProcessPropertyValue " + p.toString()));
        }
        return pvs;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if ("testBean".equals(beanName)) {
            System.out.println("testBean postProcessBeforeInitialization");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if ("testBean".equals(beanName)) {
            System.out.println("testBean postProcessAfterInitialization");
        }
        return bean;
    }
}

@Component
class TestBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        System.out.println("testBeanFactory postProcessBeanDefinitionRegistry " + registry.getClass().getSimpleName());
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("testBeanFactory postProcessBeanFactory " + beanFactory.getClass().getSimpleName());
    }
}

根据输出信息即可知道生命周期,其输出信息:

testBeanFactory postProcessBeanDefinitionRegistry DefaultListableBeanFactory
testBeanFactory postProcessBeanFactory DefaultListableBeanFactory
testBean postProcessBeforeInstantiation
testBean constructor
testBean postProcessAfterInstantiation
injectedBean constructor
testBean postProcessPropertyValue bean property 'injectedBean'
testBean setBeanFactory DefaultListableBeanFactory
testBean postProcessBeforeInitialization
testBean customInit
testBean afterPropertiesSet
testBean postProcessAfterInitialization
beanA constructor
beanB constructor
testBean ContextRefreshedEvent
========================================================
testBean ContextClosedEvent
testBean customDestroy
testBean destroy

Spring的IOC源码分析

根据上面的生命周期的测试代码来分析IOC源码,这里不会层层深入;

1
2
3
4
5
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
    this(); // 添加注解的解析器
    register(annotatedClasses); // 将注解的解析器注册到IOC容器中
    refresh();  // 更新容器
}

注解的解析器

1
2
3
4
public AnnotationConfigApplicationContext() {
    this.reader = new AnnotatedBeanDefinitionReader(this);  // 解析@Configuration等注解
    this.scanner = new ClassPathBeanDefinitionScanner(this);    // 解析@Scan注解,这里没有使用@Scan
}

这里只用到reader,忽略scanner,AnnotatedBeanDefinitionReader做了以下初始化逻辑:

  1. DefaultListableBeanFactory.dependencyComparator = AnnotationAwareOrderComparator,工厂的比较器,如@Order的先后顺序,实现利用了饿汉式单例设计模式;
  2. DefaultListableBeanFactory.autowireCandidateResolver = ContextAnnotationAutowireCandidateResolver,注入候选者Bean的解析,如@AutoWired同类型多Bean的选取;
  3. 通过DefaultListableBeanFactory.registerBeanDefinition注册6个bean;
    1. ConfigurationClassPostProcessor实现BeanDefinitionRegistryPostProcessor接口,包含BeanFactory前后处理和增强BeanFactory注解资源,如@Configuration;
    2. AutowiredAnnotationBeanPostProcessor实现InstantiationAwareBeanPostProcessor,主要是注入属性处理@AutoWired和@Value;
    3. RequiredAnnotationBeanPostProcessor实现InstantiationAwareBeanPostProcessor,主要是注入属性处理@Required;
    4. CommonAnnotationBeanPostProcessor实现InstantiationAwareBeanPostProcessor(在context包,可见是Spring的扩展),主要是注入属性处理@PostConstruct和@PreDestroy;
    5. EventListenerMethodProcessor事件监听器处理,主要是@EventListener,一般很少用,都是回调Bean的事件方法,而不会回调某个方法;
    6. DefaultEventListenerFactory事件监听器工厂配合事件监听器处理;

AnnotationConfigApplicationContext初始化完成后,所有注解相关的Bean信息已经添加到beanFactory,同时添加了ConfigurationClassPostProcessor预处理,这个类有两个作用:

  1. 在BeanFactory注册阶段解析@Configuration里面的@Bean和其他注解。
  2. 在后续处理BeanFactory阶段,通过cglib动态代理增强了@Bean注解方法,使得后续初始阶段调用注解下的方法。

注册注解类

register(annotatedClasses)会调用doRegisterBean,注册注解类的信息,会把@Primary、@Lazy等注解信息注册AnnotatedBeanDefinition里,没有什么难度,不做详细介绍。

更新容器

更新容器的代码最为复杂,也是重点分析的部分。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // Prepare this context for refreshing.
        // 初始化context环境变量
        prepareRefresh();

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

        // Prepare the bean factory for use in this context.
        // 配置BeanFactory的EL表达式解析和Resource资源获取,添加系统环境变量和属性单例到spring容器
        // 添加ApplicationContextAwareProcessor,在Bean初始化前后处理各种Aware接口
        // 添加ApplicationListenerDetector,在Bean初始化前把内部Bean转化为ApplicationListeners。
        prepareBeanFactory(beanFactory);

        try {
        // Allows post-processing of the bean factory in context subclasses.
        // 对于AnnotationConfigApplicationContext是空操作
        // 对于GenericWebApplicationContext会初始化servlet和环境的Bean
        postProcessBeanFactory(beanFactory);

        // Invoke factory processors registered as beans in the context.
        // 实例化实现BeanDefinitionRegistryPostProcessor的类,这里是ConfigurationClassPostProcessor
        // 调用BeanFactory注册的预操作和预处理
        // 实例化实现BeanFactoryPostProcessor的类
        // 调用BeanFactory的预处理
        invokeBeanFactoryPostProcessors(beanFactory);

        // Register bean processors that intercept bean creation.
        // 实例化实现BeanPostProcessor的类
        registerBeanPostProcessors(beanFactory);

        // Initialize message source for this context.
        // 初始化多国语言
        initMessageSource();

        // Initialize event multicaster for this context.
        // 注册并实例化SimpleApplicationEventMulticaster,监听Bean的ApplicationListener
        initApplicationEventMulticaster();

        // Initialize other special beans in specific context subclasses.
        // 空操作
        onRefresh();

        // Check for listener beans and register them.
        // 添加实现ApplicationListener的Bean信息,以作为后续回调
        registerListeners();

        // Instantiate all remaining (non-lazy-init) singletons.
        // 注册并实例化非@Lazy的普通Bean,BeanPostProcessor在前面已经实例化完成
        // 会涉及到属性注入的问题,下文会分析
        finishBeanFactoryInitialization(beanFactory);

        // Last step: publish corresponding event.
        // 完成实现Lifecycle接口Bean的回调(应用层用得很少)
        // 通知所用实现ApplicationListener的Bean事件ContextRefreshedEvent
        finishRefresh();
        }

        // ......

    }
}

大概逻辑可认为:

  1. 初始化context环境变量和把系统的环境变量等资源实例化成Bean交给Spring管理。
  2. 通过实现了BeanDefinitionRegistryPostProcessor的ConfigurationClassPostProcessor解析@Configuration,把里面的@Bean方法,@ComponentScan等注解下的信息或者直接导入xml添加到DefaultListableBeanFactory.beanDefinitionMap。
  3. 按PriorityOrdered、Ordered和无序等顺序序实例化实现BeanFactoryPostProcessor的类,ConfigurationClassPostProcessor也是实现了这个接口,会对@Bean下的方法通过cglib动态代理并设置RootBeanDefinition.factoryMethodName,使其在实例化阶段被调用。
  4. 按PriorityOrdered、Ordered和无序等顺序序实例化BeanPostProcessor。
  5. 注册并实例化事件广播。
  6. 添加监听实现ApplicationListener的Bean的事件。
  7. Bean信息已经都在DefaultListableBeanFactory.beanDefinitionMap,且BeanPostProcessors已经准备就绪,此时可以实例化非Lazy的Bean,并解决注入属性问题。
  8. Bean实例化完成,监听器已经准备就绪,可以通知Bean了。

这里不详细分析ConfigurationClassPostProcessor,大部分是注解解析内容,感兴趣可以自行根据测试样例添加断点Debug并查看源代码。

实例化容器

实例化过程会调用doGetBean方法。省略与测试代码无关的源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
            @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

    // 转化beanName
    final String beanName = transformedBeanName(name);
    Object bean;

    // Eagerly check singleton cache for manually registered singletons.
    // 获取还没有完全注入属性但已经构造成功的实例
    // 可解决循环依赖
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }
    else {
        //.......

        // Create bean instance.
        if (mbd.isSingleton()) {
            sharedInstance = getSingleton(beanName, () -> {
                return createBean(beanName, mbd, args);
            });
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
        }
        //.......
    }
    return (T) bean;
}
```java
通过以上简略代码可知:
1. 若有循环依赖现象则获取已经构造成功的单例。
2. 否则利用getSingleton的匿名内部类回调createBean,预处理实例化,处理可能存在的代理对象,最后调用doCreateBean
3. 无论如何都会执行getObjectForBeanInstance,处理实现FactoryBean的类。

继续查看doCreateBean省略与测试代码无关的源码:
```java
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
            throws BeanCreationException {

    // Instantiate the bean.
    BeanWrapper instanceWrapper = null;

    // 实例化Bean,并对Bean装饰,处理后续操作field
    // 实例化可通过@Bean下的method,即RootBeanDefinition.getFactoryMethodName(之前流程已经解析到RootBeanDefinition)
    // 或普通的构造方法,有参或无参
    if (instanceWrapper == null) {
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    final Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();

    // Eagerly cache singletons to be able to resolve circular references
    // even when triggered by lifecycle interfaces like BeanFactoryAware.
    // 解决循环依赖Bean,通过beanName映射singletonFactories
    addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

    // Initialize the bean instance.
    Object exposedObject = bean;
    // 通过装饰对象对依赖属性进行注入
    // 如@Bean下method的参数、@Bean(autowire)和@Autowired下field和setField注入依赖Bean
    // 后处理实例化
    populateBean(beanName, mbd, instanceWrapper);

    // 此时Bean是完整对象,预处理初始化、自定义初始化、后处理初始化。
    exposedObject = initializeBean(beanName, exposedObject, mbd);

    // ......

    return exposedObject;
}

通过以上简略代码可知:

  1. doCreateBean方法前已经预处理实例化对象,创建出新对象。
  2. 注入依赖属性后,后处理实例化对象。
  3. Bean已经实例化完成, 进一步初始化,完成后即可暴露外部。

过程均是在DefaultListableBeanFactory这个类里面实现的,从Beans层次图可以得知,继承了AbstractAutowireCapableBeanFactory,AbstractAutowire实现注入属性。 DefaultListableBeanFactory里面还实现了注入依赖的候选Bean,详情可以查看其代码。