首页 > 其他分享 >Spring Refresh() 简析

Spring Refresh() 简析

时间:2023-03-17 21:03:04浏览次数:33  
标签:初始化 beanFactory Spring beanName bean Refresh 简析 loadBeanDefinitions null


Spring IOC容器分为两部分:创建、实例化


引言
pom.xml中引入(引入当前即可,会自动把spring其他基础jar包引入):

<dependency> 
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.11.RELEASE</version>
</dependency>

然后使用:

ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");

继承体系如下:

Spring Refresh() 简析_Spring Bean


使用例子:

//获取bean  当前context就是上面拿到的ApplicationContext

MessageService messageService = context.getBean(MessageService.class);

messageService.getMessage();

-applicationContext.xml为:

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd" default-autowire="byName">


<bean id="messageService" class="test_2018_11_013.MessageServiceImpl"/>
</beans>

BeanFactory简介
作用:负责生产和管理bean实例。

 

1 BeanFactory(org.springframework.beans.factory):

作用:提供最基础的容器查看的功能,保存了bean的定义,并且可以根据不同条件获取bean,查看bean是否单利,获取bean的别名。有一个&用来表示获取工厂本身而不是获取到工厂的实例。

 

学到了什么?

    bean生命周期:一堆接口->init-method->BeanPostProcessors接口(一切就绪之后的接口)->destory-method()。

    可给bean指定别名。

    bean工厂有层级关系,找bean过程是:从子到父。

 

2 ListableBeanFactory(org.springframework.beans.factory):

作用:返回一系列bean,根据不同的条件获取。

 

学到了什么?

    提供了list的bean工厂,可以枚举每一个bean定义。或者获取bean信息或者bean的实例。使用时不需要考虑已经注册了的bean和层级关系。

 

3 EnvironmentCapable(org.springframework.core.env):

作用:实现spring上下文的接口,获取上下文。可通过如下获取:

Environment getEnvironment();

 

4 HierarchicalBeanFactory:层级分层


启动过程分析
先从入口类ClassPathXmlApplicationContext.java看起:

public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {


private Resource[] configResources;

public ClassPathXmlApplicationContext() {
}
// 如果已经有 ApplicationContext 并需要配置成父子关系,那么调用这个构造方法
public ClassPathXmlApplicationContext(ApplicationContext parent) {
super(parent);
}
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
// 如果已经有 ApplicationContext 并需要配置成父子关系,那么调用这个构造方法
setConfigLocations(configLocations);
if (refresh) {
refresh(); //重点!!!
}
}
@Override
protected Resource[] getConfigResources() {
return this.configResources;
}
.....................
.....................
}


refresh()将原来ApplicationContext销毁后重新执行初始化操作,其代码如下(AbstractApplicationContext.java 446):

@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 准备,记录容器的启动时间startupDate, 标记容器为激活,初始化上下文环境如文件路径信息,验证必填属性是否填写
prepareRefresh();


// 这步比较重要(解析),告诉子类去刷新bean工厂,这步完成后配置文件就解析成一个个bean定义,注册到BeanFactory(但是未被初始化,仅将信息写到了beanDefination的map中)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();


// 设置beanFactory类加载器,添加多个beanPostProcesser
prepareBeanFactory(beanFactory);


try {
// 允许子类上下文中对beanFactory做后期处理
postProcessBeanFactory(beanFactory);


// 调用BeanFactoryPostProcessor各个实现类的方法
invokeBeanFactoryPostProcessors(beanFactory);


// 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
// 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
// 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意,到这里 Bean 还没初始化
registerBeanPostProcessors(beanFactory);


//初始化ApplicationContext的MessageSource
initMessageSource();


//初始化ApplicationContext事件广播器
initApplicationEventMulticaster();


// 初始化子类特殊bean(钩子方法)
onRefresh();


// 注册事件监听器
registerListeners();


// 初始化所有singleton bean 重点!!重点!!
finishBeanFactoryInitialization(beanFactory);


// 广播事件,ApplicationContext初始化完成
finishRefresh();
} catch (BeansException ex) {
....................
}


refresh详细流程解析如下:
1 prepareRefresh():准备,记录容器的启动时间startupDate, 标记容器为激活,初始化上下文环境如文件路径信息,验证必填属性是否填写。


2 obtainFreshBeanFactory()
-(AbstractApplicationContext.java 536):重要!!==>初始化beanFactory,注册Bean

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
//刷新上下文环境,关闭旧的beanFactory,并创建新的
refreshBeanFactory();
//返回刚创建的beanFactory (return this.beanFactory;)
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}

2.1 obtainFreshBeanFactory()->refreshBeanFactory()
-(AbstractRefreshableApplicationContext.java 120):

@Override
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) { //关闭旧的beanFactory
destroyBeans();
closeBeanFactory();
}
try {//创建新的beanFactory(创建的是DefaultListableBeanFactory)
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId()); //然后重新设置在closeBeanFactory()置为null的serialzationId
customizeBeanFactory(beanFactory); //自定义beanFactory,设置是否允许覆盖、是否循环引用标识
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
} catch........................................
}

2.1.1 obtainFreshBeanFactory()->refreshBeanFactory()->destroyBeans()
-(AbstractApplicationContext.java 907):

protected void destroyBeans() {
getBeanFactory().destroySingletons();
}

销毁所有beans,默认实现是销毁所有缓存的单例。这里提供了一个模板方法模式,在DefaultListableBeanFactory.java、DefaultSingletonRegistry.java做了具体的实现。其中DefaultListableBeanFactory 实现了基本实现了上层所有接口含注解的AbstractAutowireCapableBeanFactory.java,所以DefaultListableBeanFactory是最牛逼的BeanFactory。


2.1.2 obtainFreshBeanFactory()->refreshBeanFactory()->closeBeanFactory()
-(AbstractRrefreshableApplicationContext.java 149):

protected final void closeBeanFactory() {
synchronized (this.beanFactoryMonitor) {
this.beanFactory.setSerializationId(null);
this.beanFactory = null;
}
}

将beanFactory和serializationId设置为null。


2.1.3 obtainFreshBeanFactory()->refreshBeanFactory()->loadBeanDefinations()  !!重要!!
-(AbstractRrefreshableApplicationContext.java 80):
根据配置加载各个bean,然后放到BeanFactory中

@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// 将beanFactory传入XmlBeanDefinitionReader中,并解析、加载配置
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);


// 配置beanDefination,环境资源加载如
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));


//加载beanFactory 重要!!
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
}


2.1.3.1 obtainFreshBeanFactory()->refreshBeanFactory()->loadBeanDefinations()->loadBeanDefinitions()
-(AbstractXmlApplicationContext.java 120):

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
Resource[] configResources = getConfigResources(); //新建一个ClassPathResource
if (configResources != null) {
reader.loadBeanDefinitions(configResources); //加载beandefation
}
String[] configLocations = getConfigLocations();//加载beandefation
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}


2.1.3.1.1 obtainFreshBeanFactory()->refreshBeanFactory()->loadBeanDefinations()->loadBeanDefinitions()->getConfigResources()
-(ClassPathXmlApplicationContext.java 202):

protected Resource[] getConfigResources() {
return this.configResources;
}


2.1.3.1.1 obtainFreshBeanFactory()->refreshBeanFactory()->loadBeanDefinations()->loadBeanDefinitions()->loadBeanDefinitions()
-(AbstractBeanDefinitionReader.java 177):

public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
Assert.notNull(resources, "Resource array must not be null");
int counter = 0;
for (Resource resource : resources) {
counter += loadBeanDefinitions(resource); //调用了XmlBeanDefintionReader.java的loadBeanDefinitions
}
return counter;
}

上面会一个个加载并返回加载的数量。


2.1.3.1.1.1 obtainFreshBeanFactory()->refreshBeanFactory()->loadBeanDefinations()->loadBeanDefinitions()->loadBeanDefinitions()->loadBeanDefinitions()
-(XmlBeanDefinitionReader.java 303):

@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(new EncodedResource(resource));
}


/**
* 从指定xml解析beanDefination
*/
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
....................................
//使用ThreadLocal存放配置文件资源
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<EncodedResource>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
........................................
try {
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
//装饰者模式包装
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
//真实从指定xml解析beanDefination !重点!
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
..................................
} catch (IOException ex) {
...................................
} finally {
.............................
}
}


//==>真实从指定xml解析beanDefination===========================
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
//将xml转为document对象
Document doc = doLoadDocument(inputSource, resource);
//用给定的dom文档注册beanDefinition
return registerBeanDefinitions(doc, resource);
}catch............................
}



接下来的解析过程就不详细探讨,到这里初始化了bean容器,将xml配置转成BeanDefinition,并注册了,发送了注册事件。

上面讲完了refresh()的obtainFreshBeanFactory()如下:

Spring Refresh() 简析_java_02


接下来我们继续往下看:

@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 准备,记录容器的启动时间startupDate, 标记容器为激活,初始化上下文环境如文件路径信息,验证必填属性是否填写
prepareRefresh();


// 这步比较重要(解析),告诉子类去刷新bean工厂,这步完成后配置文件就解析成一个个bean定义,注册到BeanFactory(但是未被初始化,仅将信息写到了beanDefination的map中)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();


// 设置beanFactory类加载器,添加多个beanPostProcesser
prepareBeanFactory(beanFactory);


try {
// 允许子类上下文中对beanFactory做后期处理
postProcessBeanFactory(beanFactory);


// 调用BeanFactoryPostProcessor各个实现类的方法
invokeBeanFactoryPostProcessors(beanFactory);


// 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
// 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
// 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意,到这里 Bean 还没初始化
registerBeanPostProcessors(beanFactory);


//初始化ApplicationContext的MessageSource
initMessageSource();


//初始化ApplicationContext事件广播器
initApplicationEventMulticaster();


// 初始化子类特殊bean(钩子方法)
onRefresh();


// 注册事件监听器
registerListeners();


// 初始化所有singleton bean 重点!!重点!!
finishBeanFactoryInitialization(beanFactory);


// 广播事件,ApplicationContext初始化完成
finishRefresh();
} catch (BeansException ex) {
....................
}

上面的基本注释已经很明显了,所以可跳过上面的直接将finishBeanFactoryInitialization(),这步负责初始化所有singleton bean。


3 finishBeanFactoryInitialization()
-AbstractApplicationContext.java 736

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 初始化名字为conversionService的bean
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}


// 初始化LoadTimeWeaverAware相关bean
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}


// 停止使用临时类加载器进行类型匹配,置null
beanFactory.setTempClassLoader(null);


// 冻结(this.configurationFrozen = true;)所有beanDefinition,不让bean继续注册
beanFactory.freezeConfiguration();


// 实例化所有剩余的(非延迟-init)单例
beanFactory.preInstantiateSingletons();
}
//---------------------------------
// 实例化所有剩余的(非延迟-init)单例
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Pre-instantiating singletons in " + this);
}


// 拿到所有beanName 去遍历
List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);


// 触发所有非懒加载的singleton bean的初始化
for (String beanName : beanNames) {
//将非RootBeanDefinition转换为RootBeanDefinition以方便后续操作,
//因为Spring上下文包括实例化所有Bean用的AbstractBeanDefinition是RootBeanDefinition
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
//如果当前“不是抽象类 && 是单例 && 不是延迟加载” 则执行
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) { //判断是否factoryBean
//返回一个共享或独立的实例
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
boolean isEagerInit;
//安全管理器部分,先不管他,有兴趣可去看
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
@Override
public Boolean run() {
return ((SmartFactoryBean<?>) factory).isEagerInit();
}
}, getAccessControlContext());
} else {
isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
//返回一个实例
getBean(beanName);
}
} else {
getBean(beanName);
}
}
}
// 为所有适合的bean触发初始化后回调
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
smartSingleton.afterSingletonsInstantiated();
return null;
}
}, getAccessControlContext());
} else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}


//进行实例bean的方法,调用getBean方法最后调到doGetBean
//-返回一个指定bean的实例,无论是共享或独立
protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
//去掉beanName前的'&',然后再拿当前beanName去别名aliasMap.get(canonicalName)取
final String beanName = transformedBeanName(name);
Object bean;


// 检查是否已创建过 ,并根据注册给定的名字返回singleton
Object sharedInstance = getSingleton(beanName);
//args为空时是获取bean,不为空是创建bean
if (sharedInstance != null && args == null) {
.........................
//返回对象bean实例,如果是(beanInstance instanceof FactoryBean),则直接返回
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {
//检查当前bean是否已被创建,是则抛异常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}


// 检查bean definition是否在该工厂已创建
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 没找到就去找parent容器
String nameToLookup = originalBeanName(name);
if (args != null) {
// 返回父容器(带参数)
return (T) parentBeanFactory.getBean(nameToLookup, args);
} else {
// 不带参数
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
//typeCheckOnly为true时,将指定的bean标记为已创建,添加进Set<String> alreadyCreated中
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}


try {
//因为Spring上下文包括实例化所有Bean用的AbstractBeanDefinition是RootBeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
//检查是否Abstract,是则抛异常
checkMergedBeanDefinition(mbd, beanName, args);


// 获取以来的所有bean
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
//然后遍历传入进行初始化
for (String dependsOnBean : dependsOn) {
if (isDependent(beanName, dependsOnBean)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
}
registerDependentBean(dependsOnBean, beanName);
getBean(dependsOnBean);
}
}


// 接下来就到了创建一个bean实例的过程,创建单例/多例
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
} catch (BeansException ex) {
。。。。。。。。。。。。。。。。
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) { //多例
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
} finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
} else { //非单例/多例处理
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
} finally {
afterPrototypeCreation(beanName);
}
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
} catch (IllegalStateException ex) {
...........
}
}
} catch (BeansException ex) {
...........
}
}


// 检查所需的类型是否与实际bean实例的类型匹配。不是则抛出异常
if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
} catch (TypeMismatchException ex) {
.............
}
return (T) bean;
}
}

 

标签:初始化,beanFactory,Spring,beanName,bean,Refresh,简析,loadBeanDefinitions,null
From: https://blog.51cto.com/u_13854513/6128388

相关文章

  • RPC原理简析
    RPC作用是什么?通过动态代理和反射透明友好地调用远程服务器。即调用过程跟本地调用服务一致,让构建分布式应用、微服务更简单。为什么要用RPC?过去的Java应用一般采用Contro......
  • idea创建Spring项目时选择Maven还是Spring initializr?
    今天在使用idea创建Spring项目时不知道选择Maven还是Springinitializr 接着都实验了一下,其实本质是一样的,使用“springinitializr”创建项目,可以直观的手动勾选依赖,......
  • 如何在非Spring容器管理的类中注入/获取 Spring容器中的 Bean?
    如何在非Spring容器管理的类中注入/获取Spring容器中的Bean?前言:此文仅限新手入行,大佬回避。我们在使用Spring开发程序的适合,Spring提供了很方便的对象管理方式,即IOC,......
  • Springboot + Swagger 访问 404 的问题
    在继承了 WebMvcConfigurerAdapter或的类重写@OverridepublicvoidaddResourceHandlers(ResourceHandlerRegistryregistry){registry.addResourceH......
  • 解决springBoot整合knife4j报错的问题
    依赖:<!--引入knife4j依赖--><dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spring-boot-starter</artifactId><version>3.0.3</ve......
  • Spring Boot + Activiti 快速实现工作流
     注:本文转自:https://mp.weixin.qq.com/s/w9-uXhm9QOXoas-h37cgFw1、概念工作流。通过计算机对业务流程自动化执行管理,主要解决的是“使在多个参与者之间按照某种预定义......
  • springboot
    自动配置Configuration注解+Bean注解//获取容器中所有的组件String[]allBean=run.getBeanDefinitionNames();for(Stringname:allBean){......
  • 【Bug】 Springboot 调用第三方接口报在 "请求目标中找到无效字符。有效字符在RFC 72
    错误信息问题原因tomcat高版本严格按照RFC3986规范解析地址。该规范只允许包含a-zA-Z0-9-_.~以及所有保留字符!*’();:@&=+$,/?#[......
  • SpringBoot---Controller
    控制器SpringBoot提供了@Controller和RestController两种注解来标识此类负责接收和处理HTTP请求。如果请求的是页面和数据,使用@Controller注解即可;如果只请求数据,可以......
  • spring cloud feign的使用
    1、引入依赖<!--远程调用feign--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-o......