The previous blogs introduced the source code of IOC and AOP of Spring framework, so how to connect these two core components to provide a better external interface? At this time, the ApplicationContext in the context package will be launched.
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("bean.xml"); Person person=(Person)context.getBean("person"); person.sayHello();
It's this simple. ApplicationContext encapsulates IOC and AOP, and provides a very convenient interface for external submission.
Let's start to analyze the source code!
Let's first look at the source code of ClassPathXmlApplicationContext:
public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext { private String[] configLocations; public ClassPathXmlApplicationContext(String configLocation) throws BeansException { this.configLocations = new String[] {configLocation}; refresh(); } public ClassPathXmlApplicationContext(String[] configLocations) throws BeansException { this.configLocations = configLocations; refresh(); } public ClassPathXmlApplicationContext(String[] configLocations, ApplicationContext parent) throws BeansException { super(parent); this.configLocations = configLocations; refresh(); } protected String[] getConfigLocations() { return this.configLocations; } }
Here, the key code is in refresh()
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext { public void refresh() throws BeansException { this.startupTime = System.currentTimeMillis(); // Load BeanFactory, subclass to implement refreshBeanFactory(); ConfigurableListableBeanFactory beanFactory = getBeanFactory(); beanFactory.registerCustomEditor(Resource.class, new ContextResourceEditor(this)); beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); beanFactory.ignoreDependencyType(ResourceLoader.class); beanFactory.ignoreDependencyType(ApplicationContext.class); postProcessBeanFactory(beanFactory); // invoke factory processors registered with the context instance for (Iterator it = getBeanFactoryPostProcessors().iterator(); it.hasNext();) { BeanFactoryPostProcessor factoryProcessor = (BeanFactoryPostProcessor) it.next(); factoryProcessor.postProcessBeanFactory(beanFactory); } if (getBeanDefinitionCount() == 0) { logger.warn("No beans defined in ApplicationContext [" + getDisplayName() + "]"); } else { logger.info(getBeanDefinitionCount() + " beans defined in ApplicationContext [" + getDisplayName() + "]"); } // Execute PostProcessors of BeanFactory invokeBeanFactoryPostProcessors(); // Register bean bean processors implementation interceptor, AOP registerBeanPostProcessors(); // Initialize MessageSource, support internationalization initMessageSource(); // Call the custom refresh code in the subclass onRefresh(); // Load all listeners refreshListeners(); // Single example of pretreatment beanFactory.preInstantiateSingletons(); // Call context refresh event publishEvent(new ContextRefreshedEvent(this)); } }
refreshBeanFactory in AbstractXmlApplicationContext
protected void refreshBeanFactory() throws BeansException { try { DefaultListableBeanFactory beanFactory = createBeanFactory(); XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); initBeanDefinitionReader(beanDefinitionReader); loadBeanDefinitions(beanDefinitionReader); this.beanFactory = beanFactory; if (logger.isInfoEnabled()) { logger.info("Bean factory for application context '" + getDisplayName() + "': " + beanFactory); } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing XML document for application context [" + getDisplayName() + "]", ex); } }
The core implementation code of IOC is encapsulated here. It should be easy to understand if you read the source code of IOC. You can read my previous blogs about IOC!
The following two blogs focus on two core functions of context: event mechanism and internationalization.