SpringIOC初始化過程
相信大家都知道Spring這個東西,我們經常來用他一些特性,比如說他的AOP,IOC,那今天就帶大家解析下SpringIOC的載入過程。
我們來看一個例子
AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(JobService.class); for (String beanname:context.getBeanDefinitionNames()) { System.out.println("--------"+beanname); } System.out.println("context.getBean(JobService.class) = " + context.getBean(JobService.class));
這點程式碼很簡單 初始化bean,然後再來拿bean,我們點進AnnotationConfigApplicationContext來看
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) { this(); register(annotatedClasses); refresh(); }
public AnnotationConfigApplicationContext() { this.reader = new AnnotatedBeanDefinitionReader(this); this.scanner = new ClassPathBeanDefinitionScanner(this); }
public GenericApplicationContext() { this.beanFactory = new DefaultListableBeanFactory(); }
在refresh()我們可以看到
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // 準備好重新整理上下文. prepareRefresh(); // 返回一個Factory 為什麼需要返回一個工廠 因為要對工廠進行初始化 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 準備bean工廠,以便在此上下文中使用。 prepareBeanFactory(beanFactory); try { // 允許在上下文子類中對bean工廠進行後處理。 在spring5 並未對此介面進行實現 postProcessBeanFactory(beanFactory); // 在spring的環境中去執行已經被註冊的 Factory processors //設定執行自定義的postProcessBeanFactory和spring內部自己定義的 invokeBeanFactoryPostProcessors(beanFactory); // 註冊postProcessor registerBeanPostProcessors(beanFactory); // 初始化此上下文的訊息源。 initMessageSource(); // 初始化此上下文的事件多播程式。 initApplicationEventMulticaster(); // 在特定上下文子類中初始化其他特殊bean。 onRefresh(); //檢查偵聽器bean並註冊它們。 registerListeners(); // 例項化所有剩餘的(非懶載入)單例。 //new 單例物件 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(); } } }
那麼這裡面最重要就是finishBeanFactoryInitialization(beanFactory);這個方法就是描述 spring的一個bean如何初始化
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { // Initialize conversion service for this context. 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)); } // Register a default embedded value resolver if no bean post-processor // (such as a PropertyPlaceholderConfigurer bean) registered any before: // at this point, primarily for resolution in annotation attribute values. if (!beanFactory.hasEmbeddedValueResolver()) { beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal)); } // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early. String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false); for (String weaverAwareName : weaverAwareNames) { getBean(weaverAwareName); } // Stop using the temporary ClassLoader for type matching. beanFactory.setTempClassLoader(null); // Allow for caching all bean definition metadata, not expecting further changes. beanFactory.freezeConfiguration(); // 例項化所有單例物件 beanFactory.preInstantiateSingletons(); }
@Override public void preInstantiateSingletons() throws BeansException { if (logger.isDebugEnabled()) { logger.debug("Pre-instantiating singletons in " + this); } // Iterate over a copy to allow for init methods which in turn register new bean definitions. // While this may not be part of the regular factory bootstrap, it does otherwise work fine. //所有bean的名字 List<String> beanNames = new ArrayList<>(this.beanDefinitionNames); // Trigger initialization of all non-lazy singleton beans... for (String beanName : beanNames) { RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { if (isFactoryBean(beanName)) { Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); 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); } } }
我們可以看到用
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
來儲存bean的名字,那this.beanDefinitionNames是一個什麼東西
/** List of bean definition names, in registration order */ private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
可以看到是beanDefinition的一個名字,那beanDefinition是個什麼呢?它是spring當中非常重要的一個概念,在這裡簡單的提一嘴 我們傳統用純java的方式怎麼new物件 是 Student stu=new Student();的方式來例項化物件,但是要交給spring的話,
先通過springScan的方式掃描到類,當他掃描到的時候 他會去new一個beanDefinition物件 他有很多子類 比如說 GenericBeanDefinition generic=new GenericBeanDefinition();然後他會把掃描到的類的各種資訊給拿出來,比如說Student的名字是什麼:
GenericBeanDefinition generic=new GenericBeanDefinition(); generic.setBeanClassName("studentService"); 類的名字 generic.setBeanClass(StudentService.class); 類路徑 generic.isSingleton(); 包括是單例還是原型
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
就放到這個Map當中 也就是
beanDefinitionMap.put("studentService",generic)這樣放進去之後,spring會看你有沒有呼叫擴充介面,擴充介面我們到後面再說 如果沒有擴充介面,就會繼續呼叫我們剛剛接著繼續的 preInstantiateSingletons()方法,這個方法來完成bean的例項化 總的一句話 BeanDefinition就是用來描述bean的,當然BeanDefinition的知識不僅僅是這些,今天只是簡單提一嘴
那麼我們現在繼續 beanDefinitionNames也就是剛剛那個Map中Key的集合,然後開始迴圈
//觸發所有非延遲載入單例beans的初始化,只要步驟呼叫getBean //根據List名字從Map當中把BeanDefinition依次拿出來開始new物件 for (String beanName : beanNames) { //合併父BeanDefinition //通過Map的名字拿BeanDefinition RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); //判斷當前類是否抽象 是否為單例 是否為懶載入 如果條件都成立 則繼續 if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { //判斷該類是否為FactoryBean FactoryBean這裡不進行講解 不懂得朋友可以去了解下 //如果不是FactoryBean if (isFactoryBean(beanName)) { Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); 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 getBean(beanName); } } }
@Override //空方法 public Object getBean(String name) throws BeansException { 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 { /** *通過name獲取beanName。這裡不使用name直接做beanName * name可能會以&字元開頭,表用呼叫者想獲取FactoryBean本身,而非FactoryBean *實現類所建立的bean。在BeanFactory中,FactoryBean的實現類和其他的bean儲存方式是一致的即 * <beanName, bean> ,beanName中沒有&字元的。所以我們需要將name的首字母&移除,這樣才能取到 *FactoryBean例項 */ final String beanName = transformedBeanName(name); Object bean; // Eagerly check singleton cache for manually registered singletons. Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { if (logger.isDebugEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.debug("Returning cached instance of singleton bean '" + beanName + "'"); } } bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { // Fail if we're already creating this bean instance: // We're assumably within a circular reference. if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // Check if bean definition exists in this factory. 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 { // No args -> delegate to standard getBean method. return parentBeanFactory.getBean(nameToLookup, requiredType); } } if (!typeCheckOnly) { markBeanAsCreated(beanName); } try { final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // 一個註解叫@DependsOn:A類建立 必須B類建立出來再建立A類 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 { getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } } // Create bean instance. 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; } }); 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 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; } } // Check if required type matches the type of the actual bean instance. 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.isDebugEnabled()) { logger.debug("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", ex); } throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } } return (T) bean; }
Object sharedInstance = getSingleton(beanName);重點為這行程式碼,我們點進去getSingleton(beanName)這個方法來看
@Override @Nullable public Object getSingleton(String beanName) { return getSingleton(beanName, true); } /** * Return the (raw) singleton object registered under the given name. * <p>Checks already instantiated singletons and also allows for an early * reference to a currently created singleton (resolving a circular reference). * @param beanName the name of the bean to look for * @param allowEarlyReference whether early references should be created or not * @return the registered singleton object, or {@code null} if none found */ @Nullable protected Object getSingleton(String beanName, boolean allowEarlyReference) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) { singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return singletonObject; }
正在要new一個物件的時候 他會呼叫getSingleton方法,那麼在這個方法中
Object singletonObject = this.singletonObjects.get(beanName);
這行程式碼是本質,那他是什麼東西 我們點進來看
/** Cache of singleton objects: bean name --> bean instance */ //用於存放完全初始化好的bean從該快取中取出bean可以直接使用 private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
很明顯 他就是個Map ConcurrentHashMap執行緒安全的Map,什麼意思 這個Map也就是我們常常說說的Spring的容器 如果從微觀角度來講 沒錯spring容器就是這個Map,如果從巨集觀上講,他就不能稱之為map 我希望大家能理解什麼意思,因為spring環境包含很多元件,各種元件包含在一起以及singletonObjects以及一些後置處理器配合完成一些工作我們稱之為Spring容器。
singletonObjects 是什麼?沒錯他就是單例池 他什麼要在單例池拿?為什麼要呼叫他?
因為他要解決Spring當中的迴圈依賴問題,相信大家既然有看原始碼的能力,相信大家也明白什麼是迴圈依賴這裡不再細說
在這個類裡也有介紹
/** Cache of early singleton objects: bean name --> bean instance */ //存放原始的bean物件用於解決迴圈依賴,注意:存到裡面的物件還沒被填充到屬性 private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
什麼意思 一個bean放到singletonObjects之後,把一個物件new出來之後,如果這個物件要迴圈引用那spring就會先把他放到earlySingletonObjects這個當中.get是因為怕物件已經放到early當中所以先去get一遍,這裡也只是簡單題一嘴
那我們繼續看
if (sharedInstance != null && args == null) {如果條件成立的話
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);直接返回撥
如果條件不成立直接else
if (isPrototypeCurrentlyInCreation(beanName)) 判斷這個類是否正在建立,什麼意思 因為spring正在建立一類的時候他會進行標識這個類我正在建立中,然後獲取bean工廠
BeanFactory parentBeanFactory = getParentBeanFactory();這裡不重要
我們繼續來看
sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } 到這一步的時候,才開始真正建立物件,這裡又一個getSingleton這個方法跟上面那個不是同一個方法,這個地方用到lambdas表示式,我們點進去看這個getSingleton
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(beanName, "Bean name must not be null"); synchronized (this.singletonObjects) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { if (this.singletonsCurrentlyInDestruction) { throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction " + "(Do not request a bean from a BeanFactory in a destroy method implementation!)"); } if (logger.isDebugEnabled()) { logger.debug("Creating shared instance of singleton bean '" + beanName + "'"); } beforeSingletonCreation(beanName); boolean newSingleton = false; boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<>(); } try { singletonObject = singletonFactory.getObject(); newSingleton = true; } catch (IllegalStateException ex) { // Has the singleton object implicitly appeared in the meantime -> // if yes, proceed with it since the exception indicates that state. singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { throw ex; } } catch (BeanCreationException ex) { if (recordSuppressedExceptions) { for (Exception suppressedException : this.suppressedExceptions) { ex.addRelatedCause(suppressedException); } } throw ex; } finally { if (recordSuppressedExceptions) { this.suppressedExceptions = null; } afterSingletonCreation(beanName); } if (newSingleton) { addSingleton(beanName, singletonObject); } } return singletonObject; } }
Object singletonObject = this.singletonObjects.get(beanName);
這裡關鍵:
第一個getSingleton:單例池拿 拿不到到快取池拿,拿不到返回null 第二個:也是先從單例池拿 如果為null, if (this.singletonsCurrentlyInDestruction)判斷物件有沒有開始建立,
然後 beforeSingletonCreation(beanName);我們點進去來看
protected void beforeSingletonCreation(String beanName) { if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } }
singletonsCurrentlyInCreation是什麼意思
/** Names of beans that are currently in creation */ private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
也是一個Lsit,什麼意思 把它放到這個List當中表示正在建立
緊接著呼叫createBean(beanName, mbd, args);開始建立物件
我們來看createBean
@Override protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { if (logger.isDebugEnabled()) { logger.debug("Creating instance of bean '" + beanName + "'"); } RootBeanDefinition mbdToUse = mbd; // Make sure bean class is actually resolved at this point, and // clone the bean definition in case of a dynamically resolved Class // which cannot be stored in the shared merged bean definition. Class<?> resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } // Prepare method overrides. try { mbdToUse.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", ex); } try { // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } } catch (Throwable ex) { throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex); } try { Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isDebugEnabled()) { logger.debug("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; } catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) { // A previously detected exception with proper bean creation context already, // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry. throw ex; } catch (Throwable ex) { throw new BeanCreationException( mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex); } }
到這裡 不要以為完了,其實還沒完最重要的部分
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
這個是第一次呼叫spring的後置處理器,spring的生命週期一共圍繞了9個後置處理器,這個是第一個
我們先不管這些後置處理器是幹嘛的 先把他找出來我們點進resolveBeforeInstantiation
@Nullable protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { Object bean = null; if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { // Make sure bean class is actually resolved at this point. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { Class<?> targetType = determineTargetType(beanName, mbd); if (targetType != null) { bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); if (bean != null) { bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } } } mbd.beforeInstantiationResolved = (bean != null); } return bean; }
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);點進來看
@Nullable protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName); if (result != null) { return result; } } } return null; }
他會先拿出來所有後置處理器 然後判斷是不是屬於他
我們返回剛剛
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
在doCreateBean裡面呼叫第二個後置處理器,我這裡都不再一一尋找了,直接列出來吧
第一次:InstantiationAwareBeanPostProcessor --postProcessBeforeInstantiation
第二次:SmartInstantiationAwareBeanPostProcessor—determineCandidateConstructors—由後置處理器決定返回那些構造方法
第三次:MergedBeanDefinitionPostProcessor——postProcessMergedBeanDefinition------快取的
第四次:SmartInstantiationAwareBeanPostProcessor—getEarlyBeanReference----把物件放到Early當中--處理迴圈引用
第五次:InstantiationAwareBeanPostProcessor—postProcessAfterInstantiation---判斷要不要填充屬性
第六次:InstantiationAwareBeanPostProcessor—postProcessPropertyValues—處理屬性的值
第七次:BeanPostProcessor—postProcessBeforeInitialization —處理AOP
第八次:BeanPostProcessor----postProcessAfterInitialization
第九次為銷燬
那麼到這裡一個完整的springBean的初始化。
轉載需標明出處 謝謝,體諒下原創,不容易。