下面以注解方式启动容器,进行代码跟踪bean的初始化过程
String basePackages = "com.cpx.service";
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(basePackages);
UserService userService = (UserService) ctx.getBean("userServiceImpl");
userService.sayHello();
ctx.close();
这里使用AnnotationConfigApplicationContext进行构造容器扫描配置,下面是它的构造方法。1、调用无参构造函数初始化reader和scanner。2、扫描配置。将注解bean封装成一个BeanDefinition对象进行描述。3、实例化bean
public AnnotationConfigApplicationContext(String... basePackages) {
this();//初始化reader和scanner
//扫描指定包,寻找bean
scan(basePackages);
//实例化bean
refresh();
}
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
createAnnotatedBeanDefReader.end();
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
扫描实际操作是在ClassPathBeanDefinitionScanner.doScan方法
protected Set doScan(String... basePackages) {
Set beanDefinitions = new LinkedHashSet<>();
for (String basePackage : basePackages) {//循环所有指定的包路径
//step1 找到所有可能的bean
Set candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
//读取@Scope设置,默认是singleton
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
//获取beanName,首先根据注解判断是否明确指定,否则根据beanDef自动生成
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
//这里candidate实例是ScannedGenericBeanDefinition,下面两个if都成立
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
//解析一些基本的注解配置 @Lazy @Primary @DependsOn @Role @Description
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
//检查beanname是否存在
if (checkCandidate(beanName, candidate)) {
// 构造BeanDefinitionHolder放到beanDefinitions中
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
//beanDefinition注册,不仅会按beanName注册,还会解析alias注册alias
//最后会放到beanFacotry的beanDefinitionMap属性存储
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
step1查找所有的bean最后是在scanCandidateComponents方法
private Set scanCandidateComponents(String basePackage) {
Set candidates = new LinkedHashSet<>();
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;
//step1 解析包下所有class文件资源
Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
for (Resource resource : resources) {//逐个判断是否是bean
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
//step2 判断是否包含指定的注解
if (isCandidateComponent(metadataReader)) {//是bean,构造BeanDefinition
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setSource(resource);
if (isCandidateComponent(sbd)) {//step3 判断
candidates.add(sbd);
}
}
}
return candidates;
}
step2处判断是否是bean条件
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
for (TypeFilter tf : this.excludeFilters) {//默认excludeFilters是空
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return false;
}
}
//默认includeFilters是 org.springframework.stereotype.Component和javax.annotation.ManagedBean两个
for (TypeFilter tf : this.includeFilters) {
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return isConditionMatch(metadataReader);
}
}
return false;
}
beandef解析完成后,下一步就是对bean进行实例化。这里有 refresh方法开始
AbstractApplicationContext.refresh方法.这个方法在初始化的时候做了很多事情,这里先把完整方法放这里,
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
//这里实例是DefaultListableBeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
//定义的BeanFactoryPostProcessor会在这里调用
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// 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();
}
}
最后bean的实例化在finishBeanFactoryInitialization(beanFactory);这一步里面。最后调用beanFactory.preInstantiateSingletons()方法实例化bean。就从这里开始看。
public void preInstantiateSingletons() throws BeansException {
//获取所有解析的beanDefinitionNames
List beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
//不是Abstract,是单例不是懒加载
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {//从工厂里获取一次,第一次肯定为null走else
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
FactoryBean> factory = (FactoryBean>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction) ((SmartFactoryBean>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
getBean(beanName);
}
}
}
// ...
}
我们看到了熟悉的getBean方法。bean的实例化也是从这个方法开始的。
getBean方法的大致逻辑
AbstractBeanFacotry.getBean()
->doGetBean()
case1->getSingleton(beanName, true)
case2->getSingleton(beanName, ObjectFactory() {
getObject(){ return createBean(beanName, mbd, args); }
};
getBean方法实际会使用doGetBean方法进行获取bean。doGetBean首先从单例缓存中获取getSingleton(beanName, true),如果获取不到就调用getSingleton(beanName, ObjectFactory)方法,然后调用ObjectFactory.getObject方法,最后是createBean方法。
bean的实例化,一个重要的类DefaultSingletonBeanRegistry
DefaultSingletonBeanRegistry{
/** 已经实例化好的单例bean */
private final Map singletonObjects = new ConcurrentHashMap<>(256);
/**半成品bean */
private final Map> singletonFactories = new HashMap<>(16);
/** 三级缓存 */
private final Map earlySingletonObjects = new ConcurrentHashMap<>(16);
/** 正在创建的beanName集合 */
private final Set singletonsCurrentlyInCreation =
Collections.newSetFromMap(new ConcurrentHashMap<>(16));
}
重要的方法getSingleton
/**
allowEarlyReference 是否从早期引用中查找,也就是从二三级缓存查找
*/
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//一级缓存是否存在
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {//不在一级缓存且在正在创建列表中
singletonObject = this.earlySingletonObjects.get(beanName);//三级缓存是否存在
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
// 二次检查一级缓存是否存在
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);//三级缓存是否存在
if (singletonObject == null) {
//二级缓存中拿出factory
ObjectFactory> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 调用factory的getObject方法,会调用实现的getEarlyBeanReference方法
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);//放入三级缓存
this.singletonFactories.remove(beanName);//二级缓存中移除
}
}
}
}
}
}
return singletonObject;
}
上面getBean方法case2的getSingleton方法
1、还是先从singletonObjects缓存中查询是否有该bean。调用getSingleton(beanName,true)。第二个参数标识是是否从早期半成品缓存存中查找该bean。如果从二级缓存命中,回调用factory的getObject方法。最后会调用到getEarlyBeanReference方法。然后将其从二级缓存移除,加入到三级缓存中。
2、没有,先将当前bean加入到正在创建列表singletonsCurrentlyInCreation中。
3、然后调用入参ObjectFactory的getObject()方法,这里上面看到入参getObject的实现最终会调用createBean方法。createBean方法最后调用doCreateBean进行bean实例的创建。
4、调用afterSingletonCreation方法将当前bean从正在创建列表删除
5、调用addSingleton方法将当前实例加到一级缓存,然后二级、三级缓存中移除。
来看AbstractAutowireCapableBeanFactory.doCreateBean方法
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {//创建bean实例
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class> beanType = instanceWrapper.getWrappedClass();
//...
// Eagerly cache singletons to be able to resolve circular references
//是否满足早期暴露条件
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
//加入到二级缓存
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {//bean初始化 属性赋值
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
//...
return exposedObject;
}
1、调用createBeanInstance方法根据beanDef进行对象实例化,这里就是根据反射先实例化,属性还未赋值
2、判断bean是否是earlySingletonExposure。判断条件:bean是单例,bean在正在创建列表singletonsCurrentlyInCreation中,当前spring支持循环依赖
如果条件成立,调用addSingletonFactory(beanName,ObjectFactory(){
getObject(){ getEarlyBeanReference(beanName, mbd, bean);}
})。
addSingletonFactory方法的具体实现就是将bean放入二级缓存singletonFactories中
3、populateBean方法对属性进行注入
这里就是依赖注入的地方,假如是a和b两个相互依赖,第一开始创建a走到这里,进行a的属性注入,也就是b。这时候获取b肯定还是从getBean(b)开始从头开始走。一步步走又走到这里进行b的属性注入,这个时候getBean(a)会调用到getSingleton(a, true)能够获取到a的实例,因为这个时候a在二级缓存中。所以b.a属性可以直接赋值。最后b创建成功,然后又回到a的populateBean里。a.b也赋值成功。
为什么三级缓存?
三级缓存主要是为了保持不同状态的bean实例。一级缓存是已经初始化好的bean。二级缓存是只是实例化,还未完成属性初始化,但是可以提前暴露给其它bean作为依赖属性进行注入。三级缓存是存储还未初始化完并且已经被其它bean引用到的。