ApplicationContext ctx = new ClassPathXmlApplicationContext("application.xml"); ctx.getBean("myBean");
It can be seen ApplicationContext and BeanFactory usage is basically the same, after initialization can get directly Bean, and then we start with the ApplicationContext is initialized to start, that is, starting with the constructor ClassPathXmlApplicationContext the start code is as follows:
public ClassPathXmlApplicationContext(String configLocation) throws BeansException { this(new String[] {configLocation}, true, null); }
. 1 public the ClassPathXmlApplicationContext ( 2 String [] configLocations, Boolean Refresh, @Nullable the ApplicationContext parent) . 3 throws BeansException { . 4 . 5 // constructor call parent class . 6 Super (parent); . 7 // set the configuration XML . 8 setConfigLocations (configLocations); . 9 // the ApplicationContext initialization 10 IF (Refresh) { . 11 Refresh (); 12 is } 13 is }
1 public void setConfigLocations(@Nullable String... locations) { 2 if (locations != null) { 3 Assert.noNullElements(locations, "Config locations must not be null"); 4 this.configLocations = new String[locations.length]; 5 for (int i = 0; i < locations.length; i++) { 6 this.configLocations[i] = resolvePath(locations[i]).trim(); 7 } 8 } 9 else { 10 this.configLocations = null; 11 } 12 }
Xml mainly used for parsing the configuration information, the path information assigned to xml configLocations, provided it is necessary to perform an initialization operation after ApplicationContext configuration information, and the final step of the refresh method, as follows:
1 @Override 2 public void refresh() throws BeansException, IllegalStateException { 3 synchronized (this.startupShutdownMonitor) { 4 // Prepare this context for refreshing. 5 //准备刷新 6 prepareRefresh(); 7 8 // Tell the subclass to refresh the internal bean factory. 9 //初始化BeanFactory,并进行XML文件读取 10 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); 11 12 //The use for the bean Factory PREPARE in the this context. 13 is // of the various function expansion BeanFactory 14 prepareBeanFactory (beanFactory); 15 16 the try { . 17 // android.permission POST-Processing Factory in context of the bean The subclasses. 18 is // subclass A method of processing do extra cover . 19 postProcessBeanFactory (beanFactory); 20 is 21 is // . Registered the Invoke Factory processors in AS Beans The context 22 is // activate various BeanFactory processor 23 is invokeBeanFactoryPostProcessors (beanFactory); 24 25 //. Processors that the Register bean bean Creation Intercept 26 // Registration interception Bean Bean processor to create, just registered here, real time call in getBean of 27 registerBeanPostProcessors (beanFactory); 28 29 // . The Initialize the Message Source for the this context 30 / / as the context initialization the message 31 is initMessageSource (); 32 33 is // the initialize Event multicaster for the this context. 34 is // initializes the application message broadcaster 35 initApplicationEventMulticaster (); 36 37 [ // the initialize OTHER Special Beans specific context in subclasses. 38 is //Left to initialize other subclasses of Bean 39 OnRefresh (); 40 41 is // the Check Register for listener Beans and Them. 42 is // Find Lestener bean to bean, all registered in the register to the message broadcaster 43 is registerListeners (); 44 is 45 // . Instantiate All remaining (non-the lazy-the init) singletons 46 is // initializes the remaining single embodiment the bean 47 finishBeanFactoryInitialization (beanFactory); 48 49 // Last STEP: publish the Corresponding Event. 50 // complete refresh, notification processor refresh process life cycle, while others notice issued ContextRefreshEvent 51 finishRefresh (); 52 } 53 54 catch (BeansException ex) { 55 if (logger.isWarnEnabled()) { 56 logger.warn("Exception encountered during context initialization - " + 57 "cancelling refresh attempt: " + ex); 58 } 59 60 // Destroy already created singletons to avoid dangling resources. 61 destroyBeans(); 62 63 // Reset 'active' flag. 64 cancelRefresh(ex); 65 66 // Propagate exception to caller. 67 throw ex; 68 } 69 70 finally { 71 // Reset common introspection caches in Spring's core, since we 72 // might not ever need metadata for singleton beans anymore... 73 resetCommonCaches(); 74 } 75 } 76 } 77 }
The main process is:
1 protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { 2 refreshBeanFactory(); 3 return getBeanFactory(); 4 }
The first step initialization BeanFactory, be read parse xml configuration
The second step is returned BeanFactory
1 @Override 2 protected final void refreshBeanFactory() throws BeansException { 3 if (hasBeanFactory()) { 4 destroyBeans(); 5 closeBeanFactory(); 6 } 7 try { 8 DefaultListableBeanFactory beanFactory = createBeanFactory(); 9 beanFactory.setSerializationId(getId()); 10 customizeBeanFactory(beanFactory); 11 loadBeanDefinitions(beanFactory); 12 synchronized (this.beanFactoryMonitor) { 13 this.beanFactory = beanFactory; 14 } 15 } 16 catch (IOException ex) { 17 throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); 18 } 19 }
1 protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { 2 // Tell the internal bean factory to use the context's class loader etc. 3 beanFactory.setBeanClassLoader(getClassLoader()); 4 beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); 5 beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); 6 7 // Configure the bean factory with context callbacks. 8 beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); 9 beanFactory.ignoreDependencyInterface(EnvironmentAware.class); 10 beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class); 11 beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); 12 beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); 13 beanFactory.ignoreDependencyInterface(MessageSourceAware.class); 14 beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); 15 16 // BeanFactory interface not registered as resolvable type in a plain factory. 17 // MessageSource registered (and found for autowiring) as a bean. 18 beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); 19 beanFactory.registerResolvableDependency(ResourceLoader.class, this); 20 beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); 21 beanFactory.registerResolvableDependency(ApplicationContext.class, this); 22 23 // Register early post-processor for detecting inner beans as ApplicationListeners. 24 beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); 25 26 // Detect a LoadTimeWeaver and prepare for weaving, if found. 27 if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { 28 beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); 29 // Set a temporary ClassLoader for type matching. 30 beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); 31 } 32 33 // Register default environment beans. 34 if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) { 35 beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); 36 } 37 if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) { 38 beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties()); 39 } 40 if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) { 41 beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment()); 42 } 43 }
The method main contents are:
1. Add support for SPEL language (e.g., # {XXX.xxx} set properties)
2. Added support for Attribute Editor
3. Set-dependent function of the interface can be ignored
4. register some fixed-dependent properties
5. Increase support of AspectJ
6. attributes relating environment variables and singleton Register to Register
1 protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { 2 // Initialize conversion service for this context. 3 if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && 4 beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) { 5 beanFactory.setConversionService( 6 beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)); 7 } 8 9 // Register a default embedded value resolver if no bean post-processor 10 // (such as a PropertyPlaceholderConfigurer bean) registered any before: 11 // at this point, primarily for resolution in annotation attribute values. 12 if (!beanFactory.hasEmbeddedValueResolver()) { 13 beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal)); 14 } 15 16 // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early. 17 String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false); 18 for (String weaverAwareName : weaverAwareNames) { 19 getBean(weaverAwareName); 20 } 21 22 // Stop using the temporary ClassLoader for type matching. 23 beanFactory.setTempClassLoader(null); 24 25 // Allow for caching all bean definition metadata, not expecting further changes. 26 beanFactory.freezeConfiguration(); 27 28 // Instantiate all remaining (non-lazy-init) singletons. 29 beanFactory.preInstantiateSingletons(); 30 }
freezeConfiguration method 26 line here is to freeze the bean definition, that is to say it can not be changed after the registration of the bean, and the default ApplicationContext will say all singleton bean is initialized in advance, which is the method preInstantiateSingletons method
1 @Override 2 public void preInstantiateSingletons() throws BeansException { 3 if (logger.isTraceEnabled()) { 4 logger.trace("Pre-instantiating singletons in " + this); 5 } 6 7 // Iterate over a copy to allow for init methods which in turn register new bean definitions. 8 // While this may not be part of the regular factory bootstrap, it does otherwise work fine. 9 List<String> beanNames = new ArrayList<>(this.beanDefinitionNames); 10 11 // Trigger initialization of all non-lazy singleton beans... 12 for (String beanName : beanNames) { 13 RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); 14 if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { 15 if (isFactoryBean(beanName)) { 16 Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); 17 if (bean instanceof FactoryBean) { 18 final FactoryBean<?> factory = (FactoryBean<?>) bean; 19 boolean isEagerInit; 20 if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { 21 isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) 22 ((SmartFactoryBean<?>) factory)::isEagerInit, 23 getAccessControlContext()); 24 } 25 else { 26 isEagerInit = (factory instanceof SmartFactoryBean && 27 ((SmartFactoryBean<?>) factory).isEagerInit()); 28 } 29 if (isEagerInit) { 30 getBean(beanName); 31 } 32 } 33 } 34 else { 35 getBean(beanName); 36 } 37 } 38 } 39 40 // Trigger post-initialization callback for all applicable beans... 41 for (String beanName : beanNames) { 42 Object singletonInstance = getSingleton(beanName); 43 if (singletonInstance instanceof SmartInitializingSingleton) { 44 final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance; 45 if (System.getSecurityManager() != null) { 46 AccessController.doPrivileged((PrivilegedAction<Object>) () -> { 47 smartSingleton.afterSingletonsInstantiated(); 48 return null; 49 }, getAccessControlContext()); 50 } 51 else { 52 smartSingleton.afterSingletonsInstantiated(); 53 } 54 } 55 } 56 }