此至,ApplicationContext 已經完成了所有的準備工做,開始初始化剩餘的 bean 了(第 11 步)。java
public void refresh() throws BeansException, IllegalStateException { // 11. 初始化剩餘的 bean (部分在 invokeBeanFactoryPostProcessors 已經初始化) finishBeanFactoryInitialization(beanFactory); }
finishBeanFactoryInitialization 主要是實例化非懶加載的 bean。git
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { // 1. 註冊 ConversionService,注意 beanName 必須爲 conversionService 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)); } // 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); // 2. 凍結全部的 bean 定義,說明註冊的 bean 定義將不被修改 beanFactory.freezeConfiguration(); // 3. 初始化剩下的 bean beanFactory.preInstantiateSingletons(); }
(1) String2DateConvertergithub
public class String2DateConverter implements Converter<String, Date> { @Override public Date convert(String source) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); try { return sdf.parse(source); } catch (ParseException e) { ; } return null; } }
(2) 註冊spring
注意:beanName 必須爲 conversionServiceapp
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> <property name="converters"> <set> <bean class="com.github.binarylei.spring01.day0728.conversionservice.String2DateConverter"/> </set> </property> </bean>
(3) 測試ide
@Test public void test() { DefaultConversionService service = new DefaultConversionService(); service.addConverter(new String2DateConverter()); Date value = service.convert("2018-08-02", Date.class); System.out.println(value); }
源代碼【DefaultListableBeanFactory】測試
public void freezeConfiguration() { this.configurationFrozen = true; this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames); }
public void preInstantiateSingletons() throws BeansException { if (this.logger.isDebugEnabled()) { this.logger.debug("Pre-instantiating singletons in " + this); } // 1. 建立剩下的單實例 bean List<String> beanNames = new ArrayList<String>(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)) { 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); } } } // 2. 篩選出實現了 SmartInitializingSingleton 接口的 bean,回調 afterSingletonsInstantiated() 方法 // @EventListener 註解的方式註冊監聽器就是在這一步完成的 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(); } } } }
天天用心記錄一點點。內容也許不重要,但習慣很重要!this