1,ApplicationContext
ApplicationContext ctx = new ClassPathXmlApplicationContext("beanFactory.xml");
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
public void setConfigLocations(String[] locations) {
if (locations != null) {
this.configLocations = new String[locations.length];
for (int i = 0; i < locations.length; i++) {
//Resolve the profile address and record it
this.configLocations[i] = resolvePath(locations[i]).trim();
}
}
else {
this.configLocations = null;
}
}
2. Extended Functions
if (refresh) {
refresh();
}
//Almost all the core functions of Application Context are implemented in this method, and the logic is clear and clear.
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//1. Prepare to refresh the context, such as initialization and validation of system attributes and environment variables.
prepareRefresh();
//2. Initialize BeanFactory and read the XML file
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//3. Fill in BeanFactory with various functions
prepareBeanFactory(beanFactory);
try {
//Empty implementation, left to subclass extension
postProcessBeanFactory(beanFactory);
//4. Activate various BeanFactory processors
invokeBeanFactoryPostProcessors(beanFactory);
//5. Register BeanPostProcessor, which is just registration. The real call is at getBean time.
registerBeanPostProcessors(beanFactory);
//6. Initialize Message Source for Context, Internationalize Processing
initMessageSource();
//7. Initialize application message broadcasting and put it into application Event Multicaster
initApplicationEventMulticaster();
//Empty implementations, leaving subclass implementations to initialize other bean s
onRefresh();
//8. Find Listener bean s in all registered beans and register them in the broadcast
registerListeners();
//9. Initialization of non-delayed loading singletons
finishBeanFactoryInitialization(beanFactory);
//10. Complete the refresh process, notify the life processor of the refresh process, and issue ContextRefreshEvent to notify others
finishRefresh();
}
}
}
Step 1: Prepare to refresh the context
//Preparations, such as initialization and validation of system attributes and environment variables
protected void prepareRefresh() {
this.startupDate = System.currentTimeMillis();
synchronized (this.activeMonitor) {
this.active = true;
}
//Empty implementation, leaving subclass coverage
initPropertySources();
//Verify that all required properties files have been put into the environment
getEnvironment().validateRequiredProperties();
}
Step 2: Load BeanFactory
//After this function, ApplicationContext has all the functions of BeanFactory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
//Initialize the BeanFactory, read the XML file, and record the resulting beanFactory for later retrieval.
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
return beanFactory;
}
@Override
protected final void refreshBeanFactory() throws BeansException {
try {
//Direct new DefaultListable BeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
//Customized BeanFactory, where an extension of BeanFactory has begun
customizeBeanFactory(beanFactory);
//Load BeanDefinition
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
//Recording beanFactory
this.beanFactory = beanFactory;
}
}
}
//Customized BeanFactory, where an extension of BeanFactory has begun
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
//Sets whether to allow objects with different definitions of the same name to be overwritten
if (this.allowBeanDefinitionOverriding != null) {
beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
//Setting whether to allow cyclic dependencies between bean s
if (this.allowCircularReferences != null) {
beanFactory.setAllowCircularReferences(this.allowCircularReferences);
}
//Support for @Qualifier and @Autowire annotations is provided
beanFactory.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
}
//Load BeanDefinition
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory){
//Create XmlBean Definition Reader to read the XML configuration file
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
//Setting environment variables for XmlBean Definition Reader
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
initBeanDefinitionReader(beanDefinitionReader);
//After that, the following logic is the same as the read configuration file in BeanFactory.
loadBeanDefinitions(beanDefinitionReader);
}
Step 3: Fill in BeanFactory with various functions
prepareBeanFactory(beanFactory);
//Spring completed the configuration analysis before entering the function prepareBeanFactory, and the functional extension of ApplicationContext expanded here.
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
beanFactory.setBeanClassLoader(getClassLoader());
//Setting up the SpEL processor for the expression language of the bean Factory, Spring 3 adds support for the expression language.
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
//Add a default property editor for beanFactory to parse Date (type 2018-07-27) in the configuration file
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
//5.1 Add the ApplicationContext Aware Processor processor, as shown in the following analysis
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
//It was analyzed at 5.1, and the dependency was ignored here.
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
//Some of the code was deleted later.
}
5.1. Adding Application Context Aware Processor Processor Processor
//Application Context Aware Processor implements BeanPostProcessor, which we analyzed in the Initial Bean of Spring Source Analysis 4. Spring activates init-method
//Before and after, BeanPostProcessor's before and after methods are invoked. Let's take a look at the two methods of ApplicationContextAware Processor that return directly without processing.
public Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
public Object postProcessBeforeInitialization(final Object bean, String beanName){
//Delete part of the code and leave the core code
invokeAwareInterfaces(bean);
return bean;
}
//After the bean s that implement these interfaces are initialized, the corresponding resources can be obtained, and the corresponding properties have been set on this side, so dependency notes need to be made in Spring.
//Ignore them when entering, as shown in the following code
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof Aware) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(
new EmbeddedValueResolver(this.applicationContext.getBeanFactory()));
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
}
Step 4: Activate various BeanFactory processors
Note that BeanFactoryPostProcessor, not BeanPostProcessor. The BeanFactoryPostProcessor interface is similar to BeanPostProcessor in that it defines bean s.
For processing, the Spring IOC container allows BeanFactoryPostProcessor to read configuration metadata and modify it before the container instantiates any other bean s. Ordered connection can be implemented
Port to set the execution order of BeanFactoryPostProcessor. Typical application of BeanFactoryPostProcessor: Property Placeholder Configurer.
Property Placeholder Configurer indirectly inherits the BeanFactoryPostProcessor interface, and when Spring loads any configuration of beans that implement this interface, it will be in beans.
After the factory loads all the bean configurations, it executes the postProcessBeanFactory method. The postProcessBeanFactory method is implemented in Property Resource Configurer.
It is through the implementation of the BeanFactoryPostProcessor interface that the configuration is converted to the appropriate type and the configuration content is finally told to BeanFactory.
BeanFactory retrieves configuration information before instantiating any bean, so it can correctly parse variable references in the bean description file.
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
//To be added
}
Step 5: Register BeanPost Processor
// This is just registration, not invocation. The real invocation is done in the bean instantiation stage. BeanFactory does not realize automatic registration of post-processor. It needs manual registration, but
// Implementation of automatic registration function in Application Context
registerBeanPostProcessors(beanFactory);
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
//Get the id names of all bean s configured in the configuration file that implement the BeanPostProcessor interface
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
//High priority
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
//Sorted
List<String> orderedPostProcessorNames = new ArrayList<String>();
//Disordered
List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
for (String ppName : postProcessorNames) {
if (isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
//Priority sorting and registration
OrderComparator.sort(priorityOrderedPostProcessors);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
//Sort and register sorting
OrderComparator.sort(orderedPostProcessors);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
//Registration of disorders
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
OrderComparator.sort(internalPostProcessors);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector());
}
private void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {
for (BeanPostProcessor postProcessor : postProcessors) {
beanFactory.addBeanPostProcessor(postProcessor);
}
}
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
//Deletion first ensures the uniqueness of the beanPostProcessor. In fact, the beanPostProcessors attribute is used to record the beanPostProcessor.
this.beanPostProcessors.remove(beanPostProcessor);
this.beanPostProcessors.add(beanPostProcessor);
if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
this.hasInstantiationAwareBeanPostProcessors = true;
}
if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
this.hasDestructionAwareBeanPostProcessors = true;
}
}
List<BeanPostProcessor> beanPostProcessors = new ArrayList<BeanPostProcessor>();
Step 6: Initialize Message Source for Context and Internationalize Processing
initMessageSource();
protected void initMessageSource() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
//If messageSource is configured in the container, this property is hardcoded
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
}
else {
//If not configured, a temporary new MessageSource
DelegatingMessageSource dms = new DelegatingMessageSource();
dms.setParentMessageSource(getInternalParentMessageSource());
this.messageSource = dms;
//Register in Container
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
}
}
Step 7: Initialize application message broadcasting and put it into application Event Multicaster
initApplicationEventMulticaster();
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
//If user-defined, use user-defined
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
}
else {
//Otherwise, use the default Application Event Multicaster
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
}
}
Step 8: Find Listener bean s in all registered beans and register them in the broadcast
registerListeners();
protected void registerListeners() {
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
//Monitor Processor for Configuration File Registration
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String lisName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(lisName);
}
}
Step 9: Initialize the non-delayed loading singleton
finishBeanFactoryInitialization(beanFactory);
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
//Configuring Conversion Service is also a type converter
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));
}
//Freeze configuration, freeze all bean definitions, indicating that registered bean definitions will not be modified or processed further
beanFactory.freezeConfiguration();
//Initialize non-delayed loading, and the default behavior of ApplicationContext is to instantiate all non-delayed loading instances ahead of time at startup
beanFactory.preInstantiateSingletons();
}
public void preInstantiateSingletons() throws BeansException {
List<String> beanNames;
synchronized (this.beanDefinitionMap) {
beanNames = new ArrayList<String>(this.beanDefinitionNames);
}
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
//Non-abstract, singleton, non-delayed loading
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
boolean isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
if (isEagerInit) {
getBean(beanName);
}
}
else {
//Initialize bean s
getBean(beanName);
}
}
}
}
Step 10: Complete the refresh process
//Notify the life processor refresh process and issue ContextRefreshEvent to notify others
finishRefresh();
protected void finishRefresh() {
//Initialize Lifecycle Processor
initLifecycleProcessor();
//Start all bean s that implement the Lifecycle interface
getLifecycleProcessor().onRefresh();
//Send the ContextRefreshedEvent event to ensure that the corresponding listener can do further processing
publishEvent(new ContextRefreshedEvent(this));
}