本篇我们一起来简单的看一下Spring Framework IoC容器启动停止。我们从上一篇的代码入手:
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.eleven.thinking.in.spring.ioc.overview.container;
import org.eleven.thinking.in.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Map;
/**
* 注解能力 {@link ApplicationContext} 作为 IoC 容器示例
*
* @author <a href="mailto:[email protected]">eleven</a>
* @since
*/
@Configuration
public class AnnotationApplicationContextAsIoCContainerDemo {
public static void main(String[] args) {
// 创建 BeanFactory 容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 将当前类 AnnotationApplicationContextAsIoCContainerDemo 作为配置类(Configuration Class)
applicationContext.register(AnnotationApplicationContextAsIoCContainerDemo.class);
// 启动应用上下文
applicationContext.refresh();
// 依赖查找集合对象
lookupCollectionByType(applicationContext);
// 关闭应用上下文
applicationContext.close();
}
/**
* 通过 Java 注解的方式,定义了一个 Bean
*/
@Bean
public User user() {
User user = new User();
user.setId(1L);
user.setName("eleven");
return user;
}
private static void lookupCollectionByType(BeanFactory beanFactory) {
if (beanFactory instanceof ListableBeanFactory) {
ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;
Map<String, User> users = listableBeanFactory.getBeansOfType(User.class);
System.out.println("查找到的所有的 User 集合对象:" + users);
}
}
}
我们从applicationContext.refresh();这行代码如下,applicationContext的这个方法refresh()翻译过来是刷新的意思,其实这里就是创建整个应用上下文的入口,主要代码如下:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
/**
* 1.刷新预处理
*/
// Prepare this context for refreshing.
prepareRefresh();
/**
* 2.阅读XML中的信息,注册BeanDefinition
* obtainFreshBeanFactory 获取 beanFactory 实例并且完成BeanDefinition的注册工作
*/
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
/**
* 3.beanFactory 加载应用上下文中的内建Bean和非Bean对象
*/
prepareBeanFactory(beanFactory);
try {
// 4. Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
/**
* 执行bean后场处理器,执行完毕
* 解析BeanDefinition对象,put到map里
* 再次执行bean后置工厂处理器
*/
// 5. Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// 6. Register bean processors that intercept bean creation.
//注册bean的后置处理器来方便拦截bean的创建
registerBeanPostProcessors(beanFactory);
// 7.Initialize message source for this context.
initMessageSource();
// 8.Initialize event multicaster for this context.
initApplicationEventMulticaster();
// 9.Initialize other special beans in specific context subclasses.
onRefresh();
// 10.Check for listener beans and register them.
registerListeners();
// 11.创建单实例业务Bean(非懒加载单例bean)
// 服务启动的时候,就会初始化所有的单例bean
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// 12.Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
启动的步骤如下:
- 刷新预处理;
- 阅读XML中的信息,注册BeanDefinition;
- beanFactory 加载应用上下文中的内建Bean和非Bean对象;
- 执行beanFactory后处理器;
- 执行bean后处理器;
- 注册bean的后置处理器来方便拦截bean的创建;
- Initialize message source for this context;
- Initialize event multicaster for this context;
- Initialize other special beans in specific context subclasses;
- Check for listener beans and register them;
- 创建单实例业务Bean(非懒加载单例bean);
- 完成创建.
另外一方面我们再来看一下停止的方法,代码如下:
@Override
public void destroySingletons() {
super.destroySingletons();
updateManualSingletonNames(Set::clear, set -> !set.isEmpty());
clearByTypeCache();
}
停止的步骤如下:
- 销毁所有的Bean对象;
- 销毁相关的容器。