spring-core-3-29 | Spring IoC容器生命周期:IoC容器启停过程中发生了什么?
Spring 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 i
·
Spring 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.geekbang.thinking.in.spring.ioc.overview.container;
import org.geekbang.thinking.in.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
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;
/**
* 29 | Spring IoC容器生命周期:IoC容器启停过程中发生了什么?
* 只是一个大概介绍
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</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();
/*
applicationContext的refresh()方法就是以前针对spring启动过程分析的核心方法, 这里只是简单一讲,
点进去看看实现:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// synchronized 这里加锁是因为applicationContext可以在程序的任何位置创建,
而spring 的设计者并不知道你会不会多线程创建什么的, 当然要加锁
// Prepare this context for refreshing. 看下面讲解
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// 这里去刷新一个内部的beanFactory, 而且是用子类来实现
// 有两种可能, 一种是空实现, 一种是抽象实现, 看下面讲解
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// 这里面会有一大堆操作,
// 里面有两个方法涉及到前面我们讲的内建的 bean的注入和非bean(依赖)注入
// beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
// beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
// 后面这里也会有详细讲解
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// 这个方法就是一个BeanFactory的扩展点, 可以自己对BeanFactory(容器)进行API的扩展
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
// 上面调整完了这里执行
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 这个方法则是对Bean进行调整, 就是对注入的用户定义的bean的调整
// 这里只是注册, 具体的调用是在BeanFactory中进行的
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();
}
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();
}
}
}
protected void prepareRefresh() {
// Switch to active. 记录一下启动的时间, 那么就可以记录初始化总共用了多少时间之类的
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
}
else {
logger.debug("Refreshing " + getDisplayName());
}
}
// Initialize any placeholder property sources in the context environment.
// 后面在 Environment抽象里面会讲到这一部分
initPropertySources();
// Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties
// 与校验相关的一个部分
getEnvironment().validateRequiredProperties();
// Store pre-refresh ApplicationListeners...
// earlyApplicationListeners会在spring的事件中进行分析, 这个场景比较复杂
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
// Reset local application listeners to pre-refresh state.
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<>();
}
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 看得出来这里提供的是一个不完整的实现, 下面两个方法都是抽象实现.
// refreshBeanFactory有一个常见的实现就是
// org.springframework.context.support.AbstractRefreshableApplicationContext.
refreshBeanFactory, 看后面
refreshBeanFactory();
return getBeanFactory();
// 特别注意一定, 玩游戏看颜色, 学技术看版本
// 我们分析用的是5.2.2.RELEASE版本, 如果低于或高于这个版本, 这里看到的代码都不一样
// 如果用的是SNAPSHOT版本, 源码可能会随之覆盖和更新, 因此一定要用RELEASE版本或MILESTONE版本
}
@Override
protected final void refreshBeanFactory() throws BeansException {
// 如果存在BeanFactory就先销毁
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 之前看过的, 创建一个DefaultListableBeanFactory,
// 这是个组合, 同时与ApplicationContext不是一个对象
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
// 读取bean的定义
loadBeanDefinitions(beanFactory);
// 这里有把锁, 同样也是因为refreshBeanFactory可以外部调用, 不是主线程调用的,
// 加了锁防止线程不安全
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
至于资源的操作其实是靠继承的父类来完成的: DefaultResourceLoader
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext
// 在web容器中的调用会复杂一些, 如tomcat等, 在springBoot中会有一些嵌套,
// 但最终还是要走上面那一套流程
*/
// 依赖查找集合对象
lookupCollectionByType(applicationContext);
applicationContext.close();
/*
关闭应用上下文
public void close() {
// 关闭要相对比较简单
synchronized (this.startupShutdownMonitor) {
doClose();
// If we registered a JVM shutdown hook, we don't need it anymore now:
// We've already explicitly closed the context.
if (this.shutdownHook != null) {
try {
Runtime.getRuntime().removeShutdownHook(this.shutdownHook);
}
catch (IllegalStateException ex) {
// ignore - VM is already shutting down
}
}
}
}
protected void doClose() {
// Check whether an actual close attempt is necessary...
if (this.active.get() && this.closed.compareAndSet(false, true)) {
if (logger.isDebugEnabled()) {
logger.debug("Closing " + this);
}
LiveBeansView.unregisterApplicationContext(this);
try {
// Publish shutdown event.
publishEvent(new ContextClosedEvent(this));
}
catch (Throwable ex) {
logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
}
// Stop all Lifecycle beans, to avoid delays during individual destruction.
if (this.lifecycleProcessor != null) {
try {
this.lifecycleProcessor.onClose();
}
catch (Throwable ex) {
logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
}
}
// Destroy all cached singletons in the context's BeanFactory.
// 可以销毁所有的bean
destroyBeans();
// Close the state of this context itself.
// 关闭掉BeanFactory
closeBeanFactory();
// Let subclasses do some final clean-up if they wish...
// 这个方法可以自定义, 实现自己需要的关闭方法
onClose();
// Reset local application listeners to pre-refresh state.
if (this.earlyApplicationListeners != null) {
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// Switch to inactive.
this.active.set(false);
}
}
*/
}
/**
* 通过 Java 注解的方式,定义了一个 Bean
* 相当于用 Java 代码 进行配置
*/
@Bean
public User user() {
User user = new User();
user.setId(1L);
user.setName("小马哥");
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);
}
}
}
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
已为社区贡献1条内容
所有评论(0)