携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第17天,点击查看活动详情
容器初始化流程
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// Prepare this context for refreshing.
prepareRefresh();
// 创建BeanFactory对象,xml解析,封装成BeanDefinition对象。这里是通过springboot启动的(不通过xml配置bean),所以在SpringApplication方法中创建context的时候就创建了befactory。
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// BeanFactoryPostProcessor会修改或添加BeanDefinition,比如@EnableAutoConfigurationImportSelector扫描到所有自动装配Configuraction并对其BeanDefinition进行注册。
invokeBeanFactoryPostProcessors(beanFactory);
// registerBeanPostProcessors(beanFactory):只是注册到BeanFactory中,具体调用是在bean初始化的时候。在所有bean实例化时,执行初始化方法前会调用所有BeaPostProcessor的postProcessBeforeInitialization方法,在执行初始化方法后会调用所有BeanPostProcessor的postProcessAfterInitialization方法(比如使用APC生成代理)。
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// Initialize message source for this context.
initMessageSource();
// 初始化事件multicaster
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// 注册事件
registerListeners();
//初始化所有剩余(非懒加载)单例
finishBeanFactoryInitialization(beanFactory);
// 最后步骤,发布相应的时间
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();
contextRefresh.end();
}
}
}
- obtainFreshBeanFactory():创建BeanFactory对象,xml解析,封装成BeanDefinition对象。这里是通过springboot启动的(不通过xml配置bean),所以在SpringApplication方法中创建context的时候就创建了benfactory。
- invokeBeanFactoryPostProcessors(beanFactory):BeanFactoryPostProcessor会修改或添加BeanDefinition,比如@EnableAutoConfiguration的@Import导入的AutoConfigurationImportSelector扫描到所有自动装配Configuraction并对其BeanDefinition进行注册。
- registerBeanPostProcessors(beanFactory):只是注册到BeanFactory中,具体调用是在bean初始化的时候。在所有bean实例化时,执行初始化方法前会调用所有BeaPostProcessor的postProcessBeforeInitialization方法,在执行初始化方法后会调用所有BeanPostProcessor的postProcessAfterInitialization方法(比如使用APC生成代理)。
- finishBeanFactoryInitialization(beanFactory):初始化所有剩余(非懒加载)单例。
总体来说就是先创建BeanFactory,后面扫描Bean拿到所有BeanDefinition,再注册Bean初始化需要的BeanPostProcessors,后面就开始初始化Bean。
我们下面看看BeanDefinition的具体内容和如何创建Bean的。
BeanDefinition
因为笔者读过Mybatis源码,所以我们来看看dao的BeanDefinition是如何生成的。(具体可以查看《Mybatis(Plus)源码阅读路径》)
下面我们大概看看,入口就是@MapperScan的@Import的处理类 MapperScannerRegistrar。
这里为扫描dao后拿到的BeanDefinition,可以看到是我们刚刚提到的AbstractApplicationContext#refresh调用invokeBeanFactoryPostProcessors(beanFactory)扫描拿到BeanDefinition。
我们继续看看processBeanDefinitions(beanDefinitions);对BeanDefinition的修改。
可以看到把dao统一修改成org.mybatis.spring.mapper.MapperFactoryBean把原始类改成了构造函数的参数,和后面使用动态代理生成Mapper是对应的。
我们大概罗列下BeanDefinition的属性:
- metadata(className、supperClassName、interfaceNames、annotationType)
- beanClass
- scope、lazyInit、dependsOn、factoryBeanName
- genericArgumentValues、propertyValues、initMethodName、destoryMethodName
- resource、source、beanName
AbstractBeanFactory#getBean——创建bean
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
String beanName = transformedBeanName(name);
Object beanInstance;
// 主动检查单例缓存是否有手动注册的单例。
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
//如果bean实例还在创建中(大概率循环引用),则直接抛出异常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 如果 bean definition 存在于父的bean工厂中,委派给父Bean工厂
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
if (!typeCheckOnly) {
// 将当前bean实例放入alreadyCreated集合里,标识这个bean准备创建了
markBeanAsCreated(beanName);
}
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
try {
if (requiredType != null) {
beanCreation.tag("beanType", requiredType::toString);
}
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 确保它的依赖也被初始化了.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
// 获得依赖的bean
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
//创建Bean实例:单例
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
//创建bean
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
beanInstance = 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);
}
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
}
Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new ScopeNotActiveException(beanName, scopeName, ex);
}
}
}
catch (BeansException ex) {
beanCreation.tag("exception", ex.getClass().toString());
beanCreation.tag("message", String.valueOf(ex.getMessage()));
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
finally {
beanCreation.end();
}
}
return adaptBeanInstance(name, beanInstance, requiredType);
}
我们直接来看看
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
是如何创建Bean的。
可以看到是根据BeanDefinition的内容进行反射出来的。如下:
Class<Order> orderClass = (Class<Order>) Class.forName("Order");
Constructor<Order> constructor = orderClass.getConstructor();
Order o = constructor.newInstance();
o.setTotalCount(1);
所以Bean的创建本质还是依赖于反射的,下面我们看看构造过程中如何使用三级缓存解决循环依赖的。
三级缓存
/** Cache of singleton objects: bean name to bean instance. */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of singleton factories: bean name to ObjectFactory. */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** Cache of early singleton objects: bean name to bean instance. */
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
- 第一层缓存(singletonObjects):单例对象缓存池,已经实例化并且属性值复制,这里的对象是成熟对象。
- 第二层缓存(earlySingletonObjects):单例对象缓存池,已经实例化但尚未属性赋值,这里的对象是半成品对象。
- 第三层缓存(singletonFactories):单例工厂的缓存。
例子:
package com.study.spring.service.impl;
import com.study.spring.dao.TestDao;
import com.study.spring.entity.TestDo;
import com.study.spring.service.TestService;
import com.study.spring.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service("testService")
public class TestServiceImpl extends ServiceImpl<TestDao, TestDo> implements TestService {
@Autowired
private UserService userService;
@Transactional(rollbackFor = Exception.class, propagation = Propagation.NESTED)
public void test() {
throw new RuntimeException();
}
}
package com.study.spring.service.impl;
import com.study.spring.dao.UserDao;
import com.study.spring.service.TestService;
import com.study.spring.service.UserService;
import com.study.spring.entity.UserDo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service("userService")
public class UserServiceImpl extends ServiceImpl<UserDao, UserDo> implements UserService {
@Autowired
private TestService testService;
@Override
@Transactional(rollbackFor = Exception.class, propagation = Propagation.NESTED)
public void test() {
UserDo userUpdate = new UserDo();
userUpdate.setId(1L);
userUpdate.setUserName("ff");
this.updateById(userUpdate);
throw new RuntimeException();
}
}
可以看到上面会产生循环依赖。
这里会先创建testService。
存放第三级缓存
AbstractBeanFactory#doCreateBean
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
放入的是一个函数接口对象,可以看到持有了beanName、mbd、bean(前面通过beanDefinition反射创建的)。
DefaultSingletonBeanRegistry#addSingletonFactory
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
populateBean——填充属性
testService存放好第三级缓存后进行填充属性。
因为testService注入了userService,所以开始创建userService。
存放第二级缓存
userService也开始填充属性。
因为userService注入了testService,所以开始处理。
可以看到使用AbstractFactory#getBean开始获取testService,因为之前已经放入三级缓存,所以从中取出放入二级缓存,此时放入二级缓存中的已经是代理对象。
后面会直接返回代理对象,userService填充完属性后返回。
存放一级缓存
继续创建testService。
调完函数接口后继续执行内部。
最后放入一级缓存。
总结
可以看到,在创建testService的时候会先把单例工厂放入三级缓存,放好之后会进行populateBean属性,填充属性的时候如果出现和属性循环依赖就会从singletonFactories从取出单例工厂实例化(如果是代理就生成代理对象),之后放入二级缓存,populateBean属性后会返回二级缓存实例用来放入第一级缓存。
可以发现二三级缓存只有循环依赖发生时才会用上(虽然三级缓存会put但是没用上),没有循环依赖就等填充好属性后如果有代理直接使用beanpostprocessor进行生成代理对象后放入一级缓存。