今天這節(jié)內(nèi)容我們一起來研究下,spring的bean的創(chuàng)建,我們一步步看著源碼往下分析.下面的方法就會帶我們進入bean的創(chuàng)建
完成bean工廠初始化
finishBeanFactoryInitialization(beanFactory);
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 初始化類型轉(zhuǎn)換器,這一部分的內(nèi)容,就是說,當前端傳過來的數(shù)據(jù)類型后臺不好解析,可以通過這個實現(xiàn)這個接口來實現(xiàn)類類型轉(zhuǎn)換
//最典型的應(yīng)用就是data轉(zhuǎn)換
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));
}
//如果之前沒有任何bean后處理器(例如PropertyPlaceholderConfigurer Bean)之前進行過注冊,請注冊默認的嵌入式值解析器,
//主要用于注釋屬性值的解析
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// 初始化 LoadTimeWeaverAwareBean 用于織入第三方模塊,在 class 文件載入 JVM 的時候動態(tài)織入
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
//將臨時類加載器設(shè)置為null
beanFactory.setTempClassLoader(null);
// 在初始化單例bean的過程中,先暫停bean的注冊,解析加載等等
beanFactory.freezeConfiguration();
//初始化非懶加載的bean
beanFactory.preInstantiateSingletons();
}
其他方法都比較簡單,咱們就直接從最后一個方法分析吧,這里干貨滿滿哈
#DefaultListableBeanFactory
@Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
//將所有的bean定義名稱添加到beanNames集合中
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// 遍歷所有的費懶加載的bean
for (String beanName : beanNames) {
//對bean定義進行合并,比如bean中引入屬性parent這一步就是來處理這個屬性的
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
//如果bean不是抽象的,不是懶加載的,并且是單例的,執(zhí)行以下步驟
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//判斷是否是工廠bean
if (isFactoryBean(beanName)) {
//如果是工廠bean,調(diào)用的時候再bean的名稱前面添加前綴符號&
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
//再次判斷bean是否是factoryBean
if (bean instanceof FactoryBean) {
final FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
getBean(beanName);
}
}
}
//再次遍歷beanNames,對實現(xiàn)了SmartInitializingSingleton接口的類實現(xiàn)處理,這里也就是說,他的功能類似于InitzationBean合格接口
//在單例bean加載完成后,做一些事情
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
//以上的方法都比較簡單,我們總結(jié)下
1:遍歷所有的非懶加載的bean
2:對bean屬性中添加了paren的屬性執(zhí)行合并處理
3:判斷某個bean是否是工廠bean,如果是,則在bean名稱前面添加前綴&再執(zhí)行處理
4:再次遍歷bean,查看bean是否實現(xiàn)了SmartInitializingSingleton,如果實現(xiàn)該接口,在進行回調(diào)處理,類似于有點像InitzationBean這個接口
接下來,我們看這個方法中重復(fù)出現(xiàn)的一個方法,getBean,沒錯,就是他,這才是我們要研究的重點,我們一起看看這個方法
代碼比較長,我們需要一步步分析啊
AbstractBeanFactory
@Override
public Object getBean(String name) throws BeansException {
//主要邏輯在dogetBean中
return doGetBean(name, null, null, false);
}
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
//規(guī)范bean名稱,就是說,你如果給bean起了別名,我們獲取bean的時候,也能找見,這一步就是執(zhí)行這個操作的
final String beanName = transformedBeanName(name);
Object bean;
// 檢查是否已經(jīng)創(chuàng)建了一個bean實例
Object sharedInstance = getSingleton(beanName);
//如果args不為為null,則證明是直接根據(jù)beanName獲取bean,最終會走到getObjectForBeanInstance
if (sharedInstance != null && args == null) {
//1.1通過bean實例獲取bean對象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
//如果args不為空,則執(zhí)行以下邏輯,執(zhí)行創(chuàng)建bean的邏輯
else {
//檢查當前這個bean是否正在創(chuàng)建,如果正在創(chuàng)建,則直接拋出異常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 檢查容器中是否已經(jīng)存在了當前這個bean
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
//不存在,證明當前容器中不存在這個bean,再去父容器中查看有沒有
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
如果args不為null直接返回父容器的結(jié)果
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
//如果指定了bean的類類型,在args不為空的情況下,直接返回bean實例
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
//從父容器獲取一個bean直接返回
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
//這里的typeCheckOnly默認就是false,這里的操作是將當前bean標記為已創(chuàng)建或?qū)⒁獎?chuàng)建
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
//合并bean定義一級檢查bean定義
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 獲取當前bean的依賴,就是spring的屬性depneds-on這個屬性配置了這個屬性全部放入dependsOn數(shù)組中
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
//執(zhí)行遍歷,并檢查當前bean的依賴,如果存在循環(huán)依賴,直接拋出異常
//這里解釋下,在spring中,如果A依賴于B,我們使用Autowird注解將B先加載,
//但是有個場景,是,B和A沒有任何的依賴關(guān)系,我們還要讓B先加載那,這個depends就起到作用了
//也就是說,spring的bean加載是沒有指定順序的,是隨意加載,用這個來控制bean的先后加載順序
//如果這里,在兩個bean中都配置了相互讓對方先加載,就會直接拋出異常
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 {
//這里是個遞歸調(diào)用,去獲取依賴項這個bean
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
//這里,我們終于走到了創(chuàng)建bean的邏輯里,這里注意下,對于spring的不同的作用于,
//如果是單例的,就走這個邏輯
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
//創(chuàng)建bean方法
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
//如果拋出異常,直接銷毀bean
destroySingleton(beanName);
throw ex;
}
});
//創(chuàng)建完bean之后,獲取當前bean
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
//如果當前bean的屬性是Prototype,則走這個邏輯
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 name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
=====================================================================================
// 如果requiredType不為null,并且不是指定的當前bean的實例,則通過轉(zhuǎn)化器處理,如果處理結(jié)果任然是null,直接
//拋出異常
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
//總結(jié)下以上步驟:
1:規(guī)范bean的名稱,因為bean有可能被起了別名,所以不管是通過原bean還是通過別名,都能訪問到
2:檢查當前bean實例是否已經(jīng)創(chuàng)建,如果創(chuàng)建了,而且args參數(shù)為null的時候,證明是獲取bean,不是創(chuàng)建bean
3:如果args不為null,就執(zhí)行創(chuàng)建bean的邏輯
4:檢查當前容器中是否存在當前的bean,子容器不存在,在區(qū)父容器中查找,找到的話,直接返回當前bean
5:將當前bean設(shè)置為已創(chuàng)建或?qū)⒁獎?chuàng)建的狀態(tài)
6:獲取bean之間的依賴關(guān)系,注意,這里指的是depends-on屬性的依賴關(guān)系,一定要記清楚,這個是對于兩個沒有關(guān)系的bean,這種依賴,是不允許相互依賴的
7:注冊依賴關(guān)系,讓被依賴項先初始化,存在相互依賴,直接拋出異常
8:對不不同的bean的作用域,執(zhí)行不同的床架bean操作,singleten,prototype,(request,session,globle-session)
9:對于requiredType不為空的,又不和當前bean實匹配,使用轉(zhuǎn)換器去處理,如果結(jié)果還是null,直接拋出異常
以上內(nèi)容比較簡答,我對getBean這個方法做了整體的分析,但是由于篇幅的限制對具體的獲取bean和創(chuàng)建bean沒有分析,獲取bean和創(chuàng)建bean我將分為兩章分別介紹!
thanks!