Spring源码(2) BeanFactory的创建

Posted by zsh on September 16, 2021

上一篇讲完了setConfigLocation(),下面就要开始解析最重要的refresh() 类概括

  • BeanFactory: Bean工厂最基础的接口
  • BeanPostProcessor: Bean自定义处理接口,实现该接口的类可以在Bean实例初始化前后对实例做一些自定义修改
  • BeanDefinitionReader: 从资源文件中读取BeanDefinition
  • XmlReaderContext: DocumentReader在读取时进行辅助的上下文类
  • BeanDefinition: Bean的基层接口,表示一个Bean的定义
  • BeanDefinitionHolder: 持有BeanDefinition的同时,还有BeanName和BeanAliases,方便后续直接获取这2个属性
  • BeanDefinitionParserDelegate: 委托类,专门解析BeanDefinition
  • Resource: 各种类型资源的顶层表示
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
AbstractApplicationContext.java
@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor){
        /**
         * 为容器刷新做准备,比如初始化propertySources
         */
        prepareRefresh();
        /**
         * 尝试获取BeanFactory,从这里开启BeanFactory的初始化
         */
        ConfigurableListableBeanFactory beanFactory=obtainFreshBeanFactory();
        /**
         * 给BeanFactory设置ClassLoader,注册内置的BeanPostProcessor,比如ApplicationContextAwareProcessor(为内部的一些Bean设置属性)
         * ApplicationListenerDetector(过滤出实现了ApplicationListener接口的Bean,将其加入ApplicationContext listeners)
         */
        prepareBeanFactory(beanFactory);
        try{
            /**
             * 抽象方法,具体子类实现后可以对BeanFactory中的Bean做一些修改
             */
            postProcessBeanFactory(beanFactory);
            /**
             * 调用所有注册的BeanFactoryPostProcessor,这个processor的作用是修改Bean的定义,比如加字段之类的,而BeanPostProcessor是修改Bean实例的属性
             */
            invokeBeanFactoryPostProcessors(beanFactory);
            /**
             * 注册所有自定义的BeanPostProcessor,该方法里还会再次筛选ApplicationListener
             */
            registerBeanPostProcessors(beanFactory);
            /**
             * 国际化消息初始化
             */
            initMessageSource();
            /**
             * 初始化事件广播,默认为SimpleApplicationEventMulticaster
             */
            initApplicationEventMulticaster();
            /**
             * 模板方法,在Bean实例初始化之前可以做一些操作
             */
            onRefresh();
            /**
             * 注册用户自定义的ApplicationListener,以及广播早期事件
             */
            registerListeners();
            /**
             * 实例化所有lazy为false的单例Bean,比如FactoryBean
             */
            finishBeanFactoryInitialization(beanFactory);
            /**
             * 初始化LifecycleProcessor,发布ContextRefreshedEvent,
             * 发布事件使用的是观察者模式,获取对event感兴趣的listener,循环调用回调函数发布
             */
            finishRefresh();
        } finally {
            resetCommonCaches();
            contextRefresh.end();
        }
    }
}

接下来看obtainFreshBeanFactory()

1
2
3
4
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    refreshBeanFactory();
    return getBeanFactory();
}

上面2个方法都在AbstractRefreshableApplicationContext,先看getBeanFactory, 作用就是返回DefaultListableBeanFactory

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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
AbstractRefreshableApplicationContext.java
@Override
public final ConfigurableListableBeanFactory getBeanFactory() {
    DefaultListableBeanFactory beanFactory = this.beanFactory;
    if (beanFactory == null) {
        throw new IllegalStateException("BeanFactory not initialized or already closed - " +
        "call 'refresh' before accessing beans via the ApplicationContext");
    }
    return beanFactory;
}
然后是refreshBeanFactory
@Override
protected final void refreshBeanFactory() throws BeansException {
    if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }
    try {
   	     // 创建的是DefaultListableBeanFactory
        DefaultListableBeanFactory beanFactory = createBeanFactory(); 
        beanFactory.setSerializationId(getId());
    	// 设置是否允许重载Bean以及是否允许循环引用
        customizeBeanFactory(beanFactory);
        // 加载Bean定义的抽象方法,xml-base的ApplicationContext实现方法在AbstractXmlApplicationContext
        loadBeanDefinitions(beanFactory);
        this.beanFactory = beanFactory;
    }
}

AbstractXmlApplicationContext.java
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

    beanDefinitionReader.setEnvironment(this.getEnvironment());
    beanDefinitionReader.setResourceLoader(this);
    /**
     * EntityResolver作用是如何加载xml文件中的内容,比如可以通过数据库或者http接口加载xml
     */
    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

    initBeanDefinitionReader(beanDefinitionReader);
    loadBeanDefinitions(beanDefinitionReader);
}
/**
 * configResources是调用ClassPathXmlApplicationContext时传入的,而configLocation是上一篇文章的setConfigLocation出来的,
 * 因此进入第二个load方法
 */
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
    Resource[] configResources = getConfigResources();
    if (configResources != null) {
        reader.loadBeanDefinitions(configResources);
    }
    String[] configLocations = getConfigLocations();
    if (configLocations != null) {
        reader.loadBeanDefinitions(configLocations);
    }
}

AbstractBeanDefinitionReader.java
@Override
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
    int count = 0;
    for (String location : locations) {
        count += loadBeanDefinitions(location);
    }
    return count;
}
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
    // 这里的resourceLoader是PathMatchingResourcePatternResolver
    ResourceLoader resourceLoader = getResourceLoader(); 
    if (resourceLoader == null) {
        throw new BeanDefinitionStoreException(
        "Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
    }

    if (resourceLoader instanceof ResourcePatternResolver) {
        try {
            Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
            // 调用了XmlBeanDefinitionReader的方法
            int count = loadBeanDefinitions(resources); 
            if (actualResources != null) {
                Collections.addAll(actualResources, resources);
            }
                return count;
        }
    } else {
        Resource resource = resourceLoader.getResource(location);
        int count = loadBeanDefinitions(resource);
        if (actualResources != null) {
            actualResources.add(resource);
        }
        return count;
    }
}

XmlBeanDefinitionReader.java
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
    /**
     * resourcesCurrentlyBeingLoaded为ThreadLocal变量,此次是防止重复加载同个资源出错
     * */
    Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
    if (!currentResources.add(encodedResource)) {
        throw new BeanDefinitionStoreException(
        "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
    }

    try (InputStream inputStream = encodedResource.getResource().getInputStream()) {
        InputSource inputSource = new InputSource(inputStream);
        if (encodedResource.getEncoding() != null) {
            inputSource.setEncoding(encodedResource.getEncoding());
        }
        return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
    } finally {
        currentResources.remove(encodedResource);
        if (currentResources.isEmpty()) {
            this.resourcesCurrentlyBeingLoaded.remove();
        }
    }
}
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
    throws BeanDefinitionStoreException {

    try {
        // 加载xml对应的Document对象,Spring通过SAX的方式读取并解析xml文件
        Document doc = doLoadDocument(inputSource, resource);
        // 注册BeanDefinition
        int count = registerBeanDefinitions(doc, resource); 
        return count;
    } ...省略cache
}
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
    // DefaultBeanDefinitionDocumentReader
    BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
    int countBefore = getRegistry().getBeanDefinitionCount();
    documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
    return getRegistry().getBeanDefinitionCount() - countBefore;
}

DefaultBeanDefinitionDocumentReader.java
/*
 * 上面的documentReader.registerBeanDefinitions(doc, createReaderContext(resource))调用了下面的方法
 */
protected void doRegisterBeanDefinitions(Element root) {
    /**
     * 这里是当递归解析嵌套的beans标签时,要先保留递归前的delegate,然后在递归中创建新的delegate
     * 在底部递归结束时恢复递归前的delegate
     */
    BeanDefinitionParserDelegate parent = this.delegate;
    this.delegate = createDelegate(getReaderContext(), root, parent);

    /**
     * 判断当前文档的profiles属性在上下文环境中是否接收,这里也就是Spring指定使用对应profile的配置文件的地方
     */
    if (this.delegate.isDefaultNamespace(root)) {
        String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
        if (StringUtils.hasText(profileSpec)) {
            String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
            profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
            if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
                return;
            }
        }
    }
    preProcessXml(root); // 模板空方法,留子类实现
    parseBeanDefinitions(root, this.delegate);
    postProcessXml(root); // 模板空方法,留子类实现

    this.delegate = parent;
}
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    if (delegate.isDefaultNamespace(root)) {
        NodeList nl = root.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                Element ele = (Element) node;
                if (delegate.isDefaultNamespace(ele)) {
                    // 非自定义标签以及命名空间下都会走到这,也就是引用的Spring定义的xml命名空间
                    parseDefaultElement(ele, delegate); 
                }
                else {
                    delegate.parseCustomElement(ele);
                }
            }
        }
    }
    else {
        delegate.parseCustomElement(root);
    }
}
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
    /**
     * 下面几个就是在解析顶层下的几个标签,包括Import, Alias, Bean, Beans, 我们着重看一下bean标签的解析
     */
    if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
        importBeanDefinitionResource(ele);
    }
    else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
        processAliasRegistration(ele);
    }
    else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
        processBeanDefinition(ele, delegate);
    }
    else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
        // 嵌套的Bean标签递归调用上面的方法
        doRegisterBeanDefinitions(ele);
    }
}
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    /**
     * BeanDefinitionHolder持有BeanDefinition,同时还有Bean name和Bean aliases,delegate.parseBeanDefinitionElement
     * 完成了对<Bean/>的解析,也就是说BeanDefinitionParserDelegate才是解析<Bean/>的关键类,该方法的解析在最下面
     */
    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    if (bdHolder != null) {
        bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
        try {
            // 注册BeanDefinition
            BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
        }
        getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    }
}

BeanDefinitionReaderUtils.java
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, 
                                          BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
    String beanName = definitionHolder.getBeanName();
    // registry是DefaultListableBeanFactory
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
    // 添加别名
    String[] aliases = definitionHolder.getAliases();
    if (aliases != null) {
        for (String alias : aliases) {
            registry.registerAlias(beanName, alias);
        }
    }
}

DefaultListableBeanFactory.java
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
    throws BeanDefinitionStoreException {

    if (beanDefinition instanceof AbstractBeanDefinition) {
        try {
        	((AbstractBeanDefinition) beanDefinition).validate();
        }
    }

    BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
    if (existingDefinition != null) {
        // 检查是否允许覆盖Bean,默认允许
        if (!isAllowBeanDefinitionOverriding()) {
        	throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
        }
        else if (existingDefinition.getRole() < beanDefinition.getRole()) {
        }
        else if (!beanDefinition.equals(existingDefinition)) {
        }
        else {
        }
        this.beanDefinitionMap.put(beanName, beanDefinition);
    }
    else {
        // 多线程下创建Bean防止不安全
        if (hasBeanCreationStarted()) {
            synchronized (this.beanDefinitionMap) {
                this.beanDefinitionMap.put(beanName, beanDefinition);
                List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
                updatedDefinitions.addAll(this.beanDefinitionNames);
                updatedDefinitions.add(beanName);
                this.beanDefinitionNames = updatedDefinitions;
                removeManualSingletonName(beanName);
            }
        }
        else {
            this.beanDefinitionMap.put(beanName, beanDefinition);
            this.beanDefinitionNames.add(beanName);
            removeManualSingletonName(beanName);
        }
    	this.frozenBeanDefinitionNames = null;
    }
	// 清除Bean创建过程中的缓存
    if (existingDefinition != null || containsSingleton(beanName)) {
    	resetBeanDefinition(beanName);
    }
    else if (isConfigurationFrozen()) {
    	clearByTypeCache();
    }
}

BeanDefinitionParserDelegate.java
@Nullable
public AbstractBeanDefinition parseBeanDefinitionElement(
    Element ele, String beanName, @Nullable BeanDefinition containingBean) {

    this.parseState.push(new BeanEntry(beanName));

    String className = null;
    // 获取className属性,放入BeanDefinition中,作为后面实例化Bean的一个关键属性
    if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
        className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
    }
    String parent = null;
    if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
        parent = ele.getAttribute(PARENT_ATTRIBUTE);
    }

    try {
        /**
           通过className创建AbstractBeanDefinition,作为BeanDefinition接口最基础也是最全面的实现
        */
        AbstractBeanDefinition bd = createBeanDefinition(className, parent);

        // 下面的方法都是解析<Bean/>的一些标签,并设置进bd中
        parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
        bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));

        parseMetaElements(ele, bd);
        parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
        parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

        parseConstructorArgElements(ele, bd);
        parsePropertyElements(ele, bd);
        parseQualifierElements(ele, bd);

        bd.setResource(this.readerContext.getResource());
        bd.setSource(extractSource(ele));

        return bd;
    }finally {
        this.parseState.pop();
    }

    return null;
}
protected AbstractBeanDefinition createBeanDefinition(
    @Nullable String className, 
    @Nullable String parentName) throws ClassNotFoundException {
		return BeanDefinitionReaderUtils.createBeanDefinition(
				parentName, className, this.readerContext.getBeanClassLoader());
}

BeanDefinitionReaderUtils.java
@Nullable
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
    // 获取<Bean/>的id和name属性
    String id = ele.getAttribute(ID_ATTRIBUTE);
    String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

    List<String> aliases = new ArrayList<>();
    if (StringUtils.hasLength(nameAttr)) {
        /* 
            name属性中可以通过,指定多个Bean的标识名,因为id标签需要遵守xml规范,不能出现一些特殊字符,
            而name则没有这些限制,比如#123,@alias。最后把name标签中的字符串按照,分割后注册进别名
         */
        String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
        aliases.addAll(Arrays.asList(nameArr));
    }

    // 当未指定id时,尝试使用第一个alias作为beanName
    String beanName = id;
    if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
        beanName = aliases.remove(0);
    }

    if (containingBean == null) {
        checkNameUniqueness(beanName, aliases, ele);
    }

    // 调用下面的重载方法
    AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
    if (beanDefinition != null) {
        if (!StringUtils.hasText(beanName)) {
            try {
                if (containingBean != null) {
                    beanName = BeanDefinitionReaderUtils.generateBeanName(
                        beanDefinition, this.readerContext.getRegistry(), true);
                }
                else {
                    /** 
                    	当alias也不存在时,生成beanName,规则是如果存在class标签,使用class标签的值,
                    	否则,如果存在parent标签,使用parent bean的className+$child
                    	否则,如果存在factoryBean标签,使用factoryBean的className+$created,还不存在则抛异常,
                    	最后在beanName末尾添加唯一数字,使得beanName在BeanFactory中全局唯一
                    */
                    beanName = this.readerContext.generateBeanName(beanDefinition);
                    String beanClassName = beanDefinition.getBeanClassName();
                    if (beanClassName != null &&
                        beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
                        !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
                        aliases.add(beanClassName);
                    }
                }
            }
        }
        String[] aliasesArray = StringUtils.toStringArray(aliases);
        return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
    }

    return null;
}    
    
public static AbstractBeanDefinition createBeanDefinition(@Nullable String parentName, 
                                                          @Nullable String className, 
                                                          @Nullable ClassLoader classLoader) throws ClassNotFoundException {
    	/**
    	  GenericBeanDefinition是一种更加通用的BeanDefinition,可以通过指定其parentName做到Bean的动态更换父类
    	*/
		GenericBeanDefinition bd = new GenericBeanDefinition();
		bd.setParentName(parentName);
		if (className != null) {
			if (classLoader != null) {
				bd.setBeanClass(ClassUtils.forName(className, classLoader));
			}
			else {
				bd.setBeanClassName(className);
			}
		}
		return bd;
	}

到此解析并注册进BeanFactory的过程就结束了,总结一下就是上下文加载配置资源文件,然后开启BeanFactory的创建,创建过程中通过DocumentReader读取xml各标签节点,通过BeanDefinitionParserDelegate解析到BeanDefinition,然后注册进BeanFactory。那有同学可能会问了,怎么没有看到依赖注入,别着急,这些下篇的getBean解析中都会讲到。