Spring Startup Process
1. The Demo
Demo
The code is very simple, the whole project structure is as follows:
pom
Rely on
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.8. RELEASE</version>
</dependency>
Copy the code
- Two classes under the service package
OrderService
,UserService
Only added@Service
Annotation, two classes under the DAO packageOrderDao
,UserDao
Only added@Repository
Annotation.MainApplication
Only in the classmain()
Methods. The code is as follows:
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = applicationContext.getBean(UserService.class);
System.out.println(userService);
OrderService orderService = applicationContext.getBean(OrderService.class);
System.out.println(orderService);
UserDao userDao = applicationContext.getBean(UserDao.class);
System.out.println(userDao);
OrderDao orderDao = applicationContext.getBean(OrderDao.class);
System.out.println(orderDao);
applicationContext.close();
}
Copy the code
AppConfig
Class is a configuration class with two annotations, plus@Configuration
Show thatAppConfig
Is a configuration class, plus@ComponentScan
Is to tellSpring
The code for which packages to scan is as follows:
@Configuration
@ComponentScan("com.tiantang.study")
public class AppConfig {}Copy the code
2. Start
- run
MainApplication
In themain()
Method, this oneSpring
The container is up and running. The console printed them out separatelyUserService
,OrderService
,UserDao
,OrderDao
thehash
Code. - So the question is, compared to the past
xml
The way you configure it, now it’s just a few lines of code, oneSpring
The container will be up and running, and we’ll be able to get it from the containerBean
.Spring
How does it work internally? Let’s analyze it step by stepSpring
Start the source code.
3. Entrance
- The entry of the program is
main()
Method, as you can see from the code, the core code is only one line,new AnnotationConfigApplicationContext(AppConfig.class)
, with this line of code, willSpring
The container is created, and then we can go throughgetBean()
The object is retrieved from the container. Therefore, the analysisSpring
Source code, fromAnnotationConfigApplicationContext
The argument constructor of the. AnnotationConfigApplicationContext
withClassPathXmlApplicationContext
The effect is the same, the former corresponding is adoptedJavaConfig
The latter corresponds to the application of technologyXML
Application of configuration
4. Basic concepts
- In the
Spring
Before reading the source code, you need to understand a few concepts. -
Spring
Will give everything toSpring
Manage the class and scan itclass
File, parse it intoBeanDefinition
In theBeanDefinition
For example, whether the class is a singleton,Bean
Type, whether lazy loading, which classes to rely on, autoassemble model.Spring
When you create an object, that’s the basisBeanDefinition
To createBean
.
-
Spring
Containers in this article can be simply understood asDefaultListableBeanFactory
, it isBeanFactory
Class, which has several very important properties:beanDefinitionMap
Is amap
For storagebean
The correspondingBeanDefinition
;beanDefinitionNames
Is aList
Collection, used to store allbean
thename
;singletonObjects
Is aMap
Is used to store all created singletonsBean
.
-
Spring
There are a lot of rear processors, but ultimately they can be divided into two types, one isBeanFactoryPostProcessor
, one isBeanPostProcessor
. The former is used for interventionBeanFactory
The latter is used for interventionBean
The creation process of. The post processor is very important,bean
And the creation ofAOP
The implementation of the backend processor is entirely dependent.
5. AnnotationConfigApplicationContext constructor
AnnotationConfigApplicationContext
The constructor argument is a mutable array that can be passed to multiple configuration classes at this timeDemo
In, only passedAppConfig
A class.- In the constructor, it is called first
this()
In thethis()
Class is initialized by calling the parent class constructorBeanFactory
, and registered seven post-processors to the container. And then callregister()
, and puts the constructor parameters intoBeanDefinitionMap
In the. The last executionrefresh()
Method, this is the wholeSpring
The core of container startup will also be analyzed in this articlerefresh()
The process and role of methods.
public AnnotationConfigApplicationContext(Class
... annotatedClasses) {
/ / initialize a the BeanFactory, DefaultListableBeanFactory as default
// Initializes a beanDefinition reader and registers seven Spring postprocessors (including BeanPostProcessor and BeanFactoryPostProcessor) with the container.
Refresh () initializes a scanner that appears not to be used later, but a new scanner is used in refresh().
this(a);// Register configuration classes in BeanDefinitionMap
register(annotatedClasses);
refresh();
}
Copy the code
5.1 this () call
this()
Will be calledAnnotationConfigApplicationContext
No parameter constructor, while inJava
The constructor of the parent class is called first. So it’s called firstAnnotationConfigApplicationContext
The parent classGeniricApplicationContext
Class, initialized in the parent classbeanFactory
, that is, directnew
aDefaultListableBeanFactory
.
public GenericApplicationContext(a) {
this.beanFactory = new DefaultListableBeanFactory();
}
Copy the code
- in
this()
Through thenew AnnotatedBeanDefinitionReader(this)
Instantiated oneBean
Reader, and toBeanDefinitionMap
Add the7
An element. throughnew ClassPathBeanDefinitionScanner(this)
A scanner is instantiated (this scanner is not used later).
public AnnotationConfigApplicationContext(a) {
/ / here will call the superclass constructor, namely first execution super (), initialize DefaultListableBeanFactory
// Initializes the bean reader and registers 7 spring native classes with Spring. Registration means placing beanDefinitionDefinitions for these 7 classes into a BeanDefinitionMap
this.reader = new AnnotatedBeanDefinitionReader(this);
// Initialize the scanner
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
Copy the code
- perform
this.reader = new AnnotatesBeanDefinitionReader(this)
Is finally called toAnnotationConfigUtils.registerAnnotationConfigProcessors(BeanDefinitionRegistry registry,Object source)
Method, this method is directed toBeanDefinitionMap
Add the7
A class, this7
A class ofBeanDefinition
(onBeanDefinition
Can refer to the previous explanation) areRootBeanDefinition
, these classes are respectivelyConfigurationClassPostProcessor
,AutowiredAnnotationBeanPostProcessor
,CommonAnnotationBeanPostProcessor
,RequiredAnnotationBeanPostProcessor
,PersistenceBeanPostProcessor
,EventListenerMethodProcessor
,DefaultEventListenerFactory
. - Of these seven classes,
ConfigurationClassPostProcessor
,AutowiredAnnotationBeanPostProcessor
,CommonAnnotationBeanPostProcessor
These three classes are so important that they are briefly introduced in the following code and analyzed in separate articles. The focus of this article is to finish the introductionSpring
Start the process.
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors( BeanDefinitionRegistry registry, @Nullable Object source) {
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
// omit some code...
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
/ / registered ConfigurationClassPostProcessor, this kind of super important, it completed the added Configuration to annotate class parsing, @ ComponentScan, @ the parsing of the Import.
if(! registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def =new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
/ / register AutowiredAnnotationBeanPostProcessor, the rear of the bean processors for processing the @autowired injection
if(! registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def =new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
/ / register RequiredAnnotationBeanPostProcessor
if(! registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def =new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
/ / registered CommonAnnotationBeanPostProcessor, used to handle such as @ Resource, @ PostConstruct annotations in conformity with the JSR - 250 standard, etc
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
if(jsr250Present && ! registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def =new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
/ / register PersistenceAnnotationBeanPostProcessor, with support for JPA
// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
if(jpaPresent && ! registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def =new RootBeanDefinition();
try {
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}
/ / registered EventListenerMethodProcessor to treatment upon the @ EventListener annotation methods
if(! registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def =new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}
/ / register DefaultEventListenerFactory, don't know what to use for the time being, from the name of the class, is an event listener's factory
if(! registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) { RootBeanDefinition def =new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}
return beanDefs;
}
Copy the code
- call
this.scanner = new ClassPathBeanDefinitionScanner(this)
To initialize a scanner that is not used when scanning packets laterSpring
Initialized to satisfy other scenarios, such as developer manual passregister(configClass)
Is used when scanning packets.
5.2 register (annotatedClasses)
Configure the incoming class annotatedClasses parsed into BeanDefinition (actual type AnnotatedGenericBeanDefinition), and then into the BeanDefinitionMap, Behind this can parse in ConfigurationClassPostProcessor annotatedClasses, AppConfig class in the demo, for example, only the parsing AppConfig class, You can only know which packages Spring is scanning (because of the @ComponentScan annotation in the AppConfig class), and you can only know which packages Spring is scanning for beans that you need to hand over to Spring to manage so that you can use Spring to create beans.
5.3 Running the refresh() method
The Refresh () method is the heart of the entire Spring container, where beans are instantiated, initialized, autowiring, AOP, and so on. Let’s take a look at the refresh() method code with some personal understanding and a brief introduction to what each line of code does, followed by a detailed analysis of several important methods
public void refresh(a) throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
// Initializes the properties profile, validates required properties, and listeners
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// Set the serialization ID for beanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Register two BeanPostProcessors and three environment-specific beans with the beanFactory
/ / the two rear processor for ApplicationContextAwareProcessor and ApplicationListenerDetector
// The previous postprocessing is a callback to the setApplicationContext() method for classes that implement the ApplicationContextAware interface,
The latter handler is used to detect the ApplicationListener class. When a Bean that implements the ApplicationListener interface is created, it is added to the listener list
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// Empty method, implemented by subclasses
postProcessBeanFactory(beanFactory);
// Implements all BeanFactoryPostProcessors, both custom and spring built-in. By default, the container is only a Spring BeanFactoryPostProcessor, namely: Spring built-in, ConfigurationClassPostProcessor (this class is very important)
/ / will perform first realized BeanDefinitionRegistryPostProcessor interface classes, then execute the spring BeanFactoryPostProcessor class
/ / postProcessorBeanFactory ConfigurationClassPostProcessor class () method for the @ the parsing of the Configuration class, @ ComponentScan scanning, and the processing of @ Import annotations
// After this step, the beanDefinitionMap of all spring-managed beans is placed in the beanFactory beanDefinitionMap
/ / at the same time ConfigurationClassPostProcessor class postProcessorBeanFactory () method after the execution, to add a container rear processor -- -- ImportAwareBeanPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);
// Register all beanPostProcessors. At this step, all beanPostProcessors are instantiated because the getBean() method is called inside the method
// Why instantiate BeanPostProcessor at this stage? Because the bean is instantiated later, and the BeanPostProcessor is used to interfere with bean creation, all BeanPostProcessors (including those defined by the developer) must be instantiated prior to bean instantiation
/ / and then register the ApplicationListenerDetector, the aim is to put ApplicationListenerDetector in the end to rear the processor
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
// Initialize MessageSource for message internationalization. Message internationalization is not used in a typical project
initMessageSource();
// Initialize event multicaster for this context.
/ / initialize event broadcast, if the container is the name for applicationEventMulticaster radio apparatus, using the radio device
/ / if not, then a SimpleApplicationEventMulticaster initialization
// The purpose of an event broadcaster is to publish events and find event listeners for the published times.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
// Performing other initialization operations, such as integrating with SpringMVC, requires initializing some other beans, but for pure Spring projects, the onFresh method is an empty method
onRefresh();
// Check for listener beans and register them.
// This step puts the bean name of the custom listener into the event broadcaster
// Early ApplicationEvents will also be published (for individual Spring projects, no ApplicationEvents will be published at this point, but when integrated with springMVC, springMVC will execute the onRefresh() method, Events will be posted here)
registerListeners();
// Instantiate the remaining non-lazy-loaded singleton bean(note: residual, non-lazy-loaded, singleton)
// Why is it surplus? If the developer customized the BeanPosrProcessor, and the BeanPostProcessor was instantiated earlier, it will not be instantiated here, so the remaining term is used here
finishBeanFactoryInitialization(beanFactory);
// The main thing to do is to publish a ContextRefreshEvent notifying everyone that the Spring container refresh has finished.
finishRefresh();
}
catch (BeansException ex) {
// Destroy the bean after an exception
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// During bean instantiation, a lot of information is cached, such as bean annotation information, but when the singleton bean is instantiated, the cached information is no longer used, so the memory resources can be freedresetCommonCaches(); }}}Copy the code
6. The refresh () method
- in
refresh()
Among the methods, the most important one isinvokeBeanFactoryPostProcessors(beanFactory)
和finishBeanFactoryInitialization(beanFactory)
. Other methods are relatively simple, the following main analysis of these two methods, the role of other methods, you can refer to the above source notes.
6.1 invokeBeanFactoryPostProcessors ()
- The purpose of this method is to perform all
BeanFactoryPostProcessor
Because ofSpring
There will be a built-inBeanFactoryPostProcessor
, i.e.,ConfigurationClassPostProcessor
(This is the only default if the developer does not customize itBeanFactoryPostProcessor
), the post-processor will parse out all the deliverables as they are processedSpring
container-managedBean
And parse them intoBeanDefinition
And then put it inBeanFactory
theBeanDefinitionMap
In the. - The method will eventually be called
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()
Method, whose main function is to perform allBeanFactoryPostProcessor
thepostProcessorBeanFactory()
Methods.BeanFactoryPostProcessor
And divided into two cases, one is direct realizationBeanFactoryPostProcessor
Interface class, another case is implementedBeanDefinitionRegistryPostProcessor
Interface (BeanDefinitionRegistryPostProcessor
inheritedBeanFactoryPostProcessor
Interface).
- Execute all of them first during execution
BeanDefinitionRegistryPostProcessor
thepostProcessorBeanDefinitionRegistry()
Method, and then executeBeanFacotryPostProcessor
thepostProcessorBeanFactory()
Methods.
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
Copy the code
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
Copy the code
- By default,
Spring
There’s a built-in oneBeanFactoryPostProcessor
, that is:ConfigurationClassPostProcessor
Class, which implementsBeanDefinitionRegistryPostProcessor
Class, so it executesConfigurationClassPostProcessor.postProcessorBeanDefinitionRegistry
.ConfigurationClassPostProcessor
theUML
The picture is as above (some non-important inheritance relationship has been deleted)
6.2 registerBeanPostProcessors ()
- The purpose of this method is to find all of them
BeanPostProcessor
And then put theseBeanPostProcessor
Instantiate (will callgetBean()
Method,getBean()
The main logic of the method is ifbean
Exists in theBeanFactory
Is returnedbean
; If not, it will be created. It will be analyzed in detail latergetBean()
Execution logic). Will thesePostProcessor
After instantiation, finally put intoBeanFactory
thebeanPostProcessors
Attribute. - Question: How do I find all of them
BeanPostProcessor
? includingSpring
Built-in and developer custom. - Due to the
refresh()
Method is executed firstinvokeBeanFactoryPostProcessor()
Method, so all customBeanPostProcessor
Classes have been scanned and resolved intoBeanDefinition
(Who does the scanning and parsing?ConfigurationClassPostProcessor
Made), deposited toBeanFactory
theBeanDefinitionMap
, so here you can find all of them by using the following line of codeBeanPostProcessor
And then throughgetBean()
Instantiate everything, and finally add the instantiated object toBeanFactory
thebeanPostProcessors
Property, the property is aList
Collection.
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true.false);
Copy the code
- And then finally re-registered
ApplicationListenerDetector
The purpose of doing this is to changeApplicationListenerDetector
Put it at the very end of the rear processor registerBeanPostProcessor()
The final call is going to bePostProcessorRegistrationDelegate.registerBeanPostProcessors()
, the following isPostProcessorRegistrationDelegate.registerBeanPostProcessors()
Method code
public static void registerBeanPostProcessors( ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
Find all BeanpostProcessors from BeanDefinitionMap
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true.false);
/ /... Omit some code...
// Find the PriorityOrdered, Ordered, and normal BeanPostProcessor implemented separately
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// The getBean() method is called here, so the BeanPostProcessor is instantiated here
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceofMergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); }}else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else{ nonOrderedPostProcessorNames.add(ppName); }}// First, register the BeanPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Add the BeanPostProcessor that implements the PriorityOrdered interface to the BeanFactory beanPostProcessors collection
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// Instantiate and add the Ordered interface and normal BeanPostProcessor to the combination of beanPostProcessors, the same logic as the postprocessor that handled PriorityOrdered
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// Now, register all regular BeanPostProcessors.
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// Finally, re-register all internal BeanPostProcessors.
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// Re-register post-processor for detecting inner beans as ApplicationListeners,
// moving it to the end of the processor chain (for picking up proxies etc).
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
/ / will finally ApplicationListenerDetector this post processor back into the same beanPostProcessor, the aim is to put it in the rear to the end of the processor
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
Copy the code
- As you can see from the source code above,
BeanPostProcessor
There is a priority, achievedPriorityOrdered
The interface has the highest priority, followed byOrdered
Interface, and finally genericBeanPostProcessor
. The one with the highest priority will be put in firstbeanPostProcessors
The front of this collection, so that when executed, the highest-priority post-processor is executed first (becauseList
The set is ordered). - So in practice, if we come across something that needs to be prioritized
BeanPostProcessor
Execute, and you can make it happenPriorityOrdered
Interface orOrdered
Interface.
6.3 initMessageSource ()
- Used to support message internationalization, which is not currently used in general projects.
6.4 initApplicationEventMulticaster ()
The method to initialize the radio apparatus, an event if the container of beanName for applicationEventMulticaster radio apparatus, is the use of the radio; If not, a SimpleApplicationEventMulticaster initialization. This class holds all applicationListeners. When an ApplicationEvent is published, the listener can determine the event type, Retrieves the ApplicationListener that is interested in the event.
initApplicationEventMulticaster()
The source code for the method is as follows (omitting some log information):
protected void initApplicationEventMulticaster(a) {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
/ / whether the spring container already exists beanName = applicationEventMulticaster event broadcast
// For example, if the developer registers one himself
// If there is one, use one that already exists; Otherwise use the spring default: SimpleApplicationEventMulticaster
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
}
else {
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster); }}Copy the code
6.5 onRefresh ()
Performing other initialization operations, such as integrating with SpringMVC, requires initializing some other beans, but for pure Spring projects, the onRefresh() method is an empty method.
6.6 registerListeners ()
This step will put the custom listener bean name into the event broadcaster, and will also publish earlier ApplicationEvents. (For individual Spring projects, no ApplicationEvents will be published at this point, but when integrated with SpringMVC, SpringMVC executes the onRefresh() method, where events are published. The method source code is as follows:
protected void registerListeners(a) {
// Register statically specified listeners first.
for(ApplicationListener<? > listener : getApplicationListeners()) { getApplicationEventMulticaster().addApplicationListener(listener); }// Find all applicationListeners from the BeanFactory, but do not initialize them because all beanPostProcessors need to modify them later during bean instantiation
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true.false);
for (String listenerBeanName : listenerBeanNames) {
// Place the beanName of the event listener into the event broadcaster
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// Release early events (pure Spring projects, no events at this point)
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if(earlyEventsToProcess ! =null) {
for(ApplicationEvent earlyEvent : earlyEventsToProcess) { getApplicationEventMulticaster().multicastEvent(earlyEvent); }}}Copy the code
6.7 finishBeanFactoryInitialization ()
This method is very important because it completes the instantiation and initialization of all non-lazy-loaded singleton beans, populates properties, and solves the problem of loop dependencies.
- (Note that the instantiation and initialization processes are deliberately separated, as in
Spring
createBean
In the process, is the first willBean
Objects are created by reflection and then passed through the post-processor (BeanPostProcessor
) to assign a value to an object’s property. So the instantiation here is going to beBean
Create out, initialize means forbean
Attribute assignment. finishBeanFactoryInitialization()
The code for the method is as follows,bean
The creation and initialization of thebeanFactory.preInstantiateSingletons()
In the implementation.
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize the transformation service
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));
}
/ / if the previous did not sign up for a similar to the rear is accomplished processor bean, then here will register a built-in rear attribute of the processor
// Here we are dealing with annotated attributes
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);
}
beanFactory.setTempClassLoader(null);
/ / the BeanFactory configurationFrozen attribute set to true, give frozenBeanDefinitionNames attribute assignment
// The purpose is not to modify the BeanDefinition of the bean elsewhere
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
// instantiate all remaining non-lazy-loaded singletons
beanFactory.preInstantiateSingletons();
}
Copy the code
6.7.1 preInstantiateSingletons () method
- This method will judge first
bean
Is it aFactoryBean
And whether to instantiate immediatelyFactoryBean
thegetObject()
Object that is returned, but is ultimately calledgetBean()
Method to instantiate an object. inBean
After the instantiation and initialization is complete, it will determineBean
Is it implementedSmartSingletonInitializing
Interface, which will be called if implementedafterSingletonInstantiated()
Methods. Tips
: It’s mentioned hereFactoryBean
, notBeanFactory
. These two names are very similar, but the effect is very different, interested friends can first themselvesGoogle
Look it up. Here is a brief introduction, and a separate article will be written laterFactoryBean
, and through theFactoryBean
To resolveSpring
withMyBatis
Principles of integration.FactoryBean
Is an interface whose implementation class registers two of them with the containerbean
, an object that implements the type represented by the class itself, and an object that implements the type represented by overridingFactoryBean
In the interfacegetObject()
Method to returnbean
. In the following example: two are registered to the containerbean
, one isMapperFactoryBean
In itself, one isUserMapper
.
@Component
public class MapperFactoryBean implements FactoryBean {
@Override
public Object getObject(a) throws Exception {
return new UserMapper();
}
@Override
publicClass<? > getObjectType() {returnUserMapper.class; }}Copy the code
- Due to the
bean
Instantiation process is too complex, will be combined with the flow chart to analyze the source code.preInstantiatedSingletons()
The execution flow chart of the method is as follows
preInstantiatedSingletons()
The following code
public void preInstantiateSingletons(a) throws BeansException {
if (logger.isDebugEnabled()) {
logger.debug("Pre-instantiating singletons in " + this);
}
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()) {// Determine if it is a factoryBean, and if it is a factoryBean, instantiate the factoryBean natively (other than the object corresponding to getObject()).
// You also need to determine whether it immediately instantiates the object returned by getObject(), based on the return value of isEagerInit() of SmartFactoryBean
if (isFactoryBean(beanName)) {
// First instantiate the BeanFactory native object, then use isEagerInit() to determine whether to instantiate the BeanFactory getObject() object of the type returned
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
finalFactoryBean<? > factory = (FactoryBean<? >) bean;boolean isEagerInit;
if(System.getSecurityManager() ! =null && factory instanceofSmartFactoryBean) { isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) ((SmartFactoryBean<? >) factory)::isEagerInit, getAccessControlContext()); }else {
isEagerInit = (factory instanceofSmartFactoryBean && ((SmartFactoryBean<? >) factory).isEagerInit()); }// If isEagerInit is true, the object of the type returned by the FactoryBean is instantiated immediately
if(isEagerInit) { getBean(beanName); }}}else{ getBean(beanName); }}}/ / in the bean is instantiated and attribute assignment is completed, if the bean implementation SmartInitializingSingleton interface, the method of the interface is the callback
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if(System.getSecurityManager() ! =null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else{ smartSingleton.afterSingletonsInstantiated(); }}}}Copy the code
- Found in the above source code, both
FactoryBean
Or ordinaryBean
, and ultimately all callsgetBean()
Method to createbean
.
6.7.2 getBean ()
getBean()
Method will calldoGetBean()
Methods.
public Object getBean(String name) throws BeansException {
return doGetBean(name, null.null.false);
}
Copy the code
6.7.3 doGetBean ()
- in
doGetBean()
Method is first fetched from the cache (i.esingletonObjects
thismap
Collection, why get it from the cache in the first place? Because fromSpring
The container gets objects and creates objects throughgetBean()
Method, for singletons, the object is created only once, so the object is fetched from the cache first. If it exists, it does not need to be created. If present in cache, then callgetObjectForBeanInstance()
Method, and returnbean
. If it does not exist in the cache, proceed. - And then get
Bean
The correspondingBeanDefinition
Object. Then judgebean
There is no dependence,String[] dependsOn = mbd.getDependsOn()
If there are dependent objects, the dependent objects are instantiated first. - Is called after the dependent object is created
getSingleton(beanName,lambda)
Method, whose second argument is alambda
The expression is really createdbean
The logic is in the method body of the expression, i.ecreateBean()
Method,createBean()
The method is createdbean
And then ingetSingleton(beanName,lambda)
Method will be createdbean
Deposit tosingletonObjects
Attribute.createBean()
Analysis later. - Created in the previous step
bean
After, eventually will still callgetObjectForBeanInstance()
. The logic of this method is relatively simple. Judge firstbean
Is it aFactoryBean
If not, return directlybean
; If so, judge againbeanName
Does it begin with an ampersand? If so, it getsFactoryBean
Is returned directlybean
; Returns if it does not begin with an ampersandFactoryBean
thegetObject()
Method return value object. doGetBean()
The method code is as follows
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if(sharedInstance ! =null && args == null) {
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 {
returnparentBeanFactory.getBean(nameToLookup, requiredType); }}if(! typeCheckOnly) {// Mark the bean as created
// Clear the beanDefinition cache (mergedBeanDefinitions)
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// Check if the bean is an abstract class
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
// Ensure that the bean on which the current bean depends is initialized
String[] dependsOn = mbd.getDependsOn();
if(dependsOn ! =null) {
for (String dep : dependsOn) {
The isDependent() method is used to determine whether the deP depends on beanName
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// Save the dependencies
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()) {
// At this point a lambda expression is passed into the getSingleton method,
// Instead of executing the lambda expression immediately, the body of the lambda method starts executing when the getObject() method of the lambda expression is called
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throwex; }}); 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);
throwex; }}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) {
throw newBeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); }}return (T) bean;
}
Copy the code
getObjectForBeanInstance()
The function of method is to basebeanName
To determine returnFactoryBean
Native objects orgetObject()
The object returned by the. ifbeanName
An ampersand is used to indicate a returnFactoryBean
Native object, otherwise returnedgetObject()
The object returned by the.
protected Object getObjectForBeanInstance( Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if(! (beanInstanceinstanceof FactoryBean)) {
throw newBeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass()); }}// If it is not a FactoryBean object or a native object that obtains a FactoryBean (native objects mean beanName begins with &)
// You can return the bean directly
if(! (beanInstanceinstanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
// If you are getting the type object returned by the getObject() method of a FactoryBean, you need to go to the following logic
// For the getObject() method, the object it returns is instantiated the first time getObject is called, and the result is cached in factoryBeanObjectCache
Object object = null;
if (mbd == null) {
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.FactoryBean<? > factory = (FactoryBean<? >) beanInstance;// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
booleansynthetic = (mbd ! =null && mbd.isSynthetic());
// Gets the object returned by the FactoryBeanobject = getObjectFromFactoryBean(factory, beanName, ! synthetic); }return object;
}
Copy the code
6.7.4 createBean ()
doGetBean()
It will end up callingcreateBean()
To create abean
.createBean()
There are two core lines of code in the method:
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
Copy the code
resolveBeforeInstantiation()
Methods in thebean
Called before instantiation, in this method the post-processor is executedInstantiationAwareBeanPostProcessor
thepostProcessBeforeInstantiation()
Methods,bean
Before instantiationbean
Process. The significance of this extension point is significant,Spring
theAOP
This is where it’s done, and you can read it if you’re interestedAnnotationAwareAspectJAutoProxyCreator
This class of source, the subsequent will be a separate article for analysis.- if
resolveBeforeInstantiation()
The return value ofnull
, the result is directly returned. If it isnull
, the execution of the method continuesdoCreateBean()
. indoCreateBean()
In the method, theBean
Instantiation, attribute assignment, initialization, etc. createBean()
Flow chart of method
createBean()
Method source code
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
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.
/ / the first call to post processor (perform all InstantiationAwareBeanPostProcessor subclass)
/ / if a subclass of InstantiationAwareBeanPostProcessor postProcessBeforeInstantiation () method returns a value is not empty, said beans need to be enhanced,
// The logic will not be executed at this point; this is where the actual use of AOP is implemented
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if(bean ! =null) {
returnbean; }}catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
// The entry to the post-processor is executed the second time
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex); }}Copy the code
6.7.5 doCreateBean ()
doCreateBean()
The method will work through reflectionBean
Create, and then pairbean
The property population (which addresses the problem of loop dependencies while the property is being populated) ends up with theBean
The callback initializes the associated methods, for example:BeanPostProcessor.postProcessBeforeInilization(),InilizaingBean.afterPropertiesSet()
To givebean
Configuration of theinitMethod()
Methods, andBeanPostProcessor.postProcessAfterInilization()
.doCreateBean()
The flow chart of execution is as follows: [doCreateBean() method flowchart]P1-jj.byteimg.com/tos-cn-i-t2…)doCreateBean()
The code for the method (with some code deleted) is as follows:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// Instantiate the bean(the entry to the second post-processor execution), the second post-processor execution, mainly to infer the constructor needed to instantiate the bean
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
finalObject bean = instanceWrapper.getWrappedInstance(); Class<? > beanType = instanceWrapper.getWrappedClass();if(beanType ! = NullBean.class) { mbd.resolvedTargetType = beanType; }// At this point, the bean object has been created successfully, but the properties have not been set and other post-processing has not been done
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if(! mbd.postProcessed) {try {
// The third time the post-processor is executed, the bean's annotation metadata information is cached (for later use in property population)
/ / this step for CommonAnnotationBeanPostProcessor, AutowiredAnnotationBeanPostProcessor, RequiredAnnotationBeanPostProcessor such processors
// The annotation information of the bean is parsed and cached into the injectionMetadataCache property in the afterprocessor
/ / for the ApplicationListenerDetector processor, but if the bean is singleton logo in singletonNames this Map types of properties
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
mbd.postProcessed = true; }}// Determine if a bean is placed in singletonFactories (exposed ahead of time to solve the problem of loop dependencies)
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
// The fourth post-processor occurs
// Retrieve the pre-exposed bean (s) in singletonFactories with the key beanName and value a lambda expression
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// Fill the properties, the fifth and sixth post-processor entry
populateBean(beanName, mbd, instanceWrapper);
// Perform the processor entry after the seventh and eighth times
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
}
return exposedObject;
}
Copy the code
createBeanInstance()
When an object is created by reflection, the post-processor is executed first, by calling the post-processor’sdeternineCondidateConstructors()
Method to infer which constructor to use to createBean
, typical representative classes areAutowiredAnnotationBeanPostProcessor
.bean
After being created by reflection, the post-processor is called againMergedBeanDefinitionPostProcessor.postProcessMargedBeanDefinition()
Method, this step is performed after the processor in order to find the added@Autowired
,@Resource
Wait for attributes and methods of annotations, and then cache the annotation information toinjectionMetadataCache
Property to facilitate the followingbean
Initialization phase (attribute assignment phase), according to@Autowired
Annotation implementation of automatic assembly. This step represents the post-processorAutowiredAnnotationBeanPostProcessor
,CommonAnnotationBeanPostProcessor
AutowiredAnnotationBeanPostProcessor is used to deal with the Spring annotations and parts of the JSR – 330 annotations, such as: the @autowired, @ Value, @ Inject. CommonAnnotationBeanPostProcessor is used to deal with the JSR – 250 annotations, such as @ Resource, @ PostConstruct, @ PreDestroy.
- The next part will be semi-finished
bean
Because it hasn’t been given yetbean
Attribute assignment, not completed autowiring, so called semi-finished) intoDefaultSingletonBeanRegistry
Of the classsingletonFactories
Attributes of,singletonFactories
A property is aMap
.key
forbeanName
And has a value ofObjectFactory
Type (actually just onelambda
Expression) when calledObjectFactory
thegetObject()
Method is executedlambda
The method body of the expression, in the current scenario,lambda
The expression is coded as follows, which is essentially executed onceBean
The rear processor. The purpose of this step is to solvebean
How to solve the problem of cyclic dependence will be analyzed in the future.
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if(! mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
// Call the postprocessed method to get the bean object exposed earlier (semi-finished)exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName); }}}return exposedObject;
}
Copy the code
- And then it will execute to
populateBean()
Method, in which it is executed twice moreBean
Post-processor, the first time the post-processor is executed is for judgmentBean
Whether to continue to populate the properties, ifInstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
Method returnfalse
, indicates that no attribute filling is carried out.bean
It’s not going to happen@Autowired
And the automatic assembly process,populateBean()
The method will just end. If the returntrue
, the following property population is performed, that is, the second post-processor is performed,InstantiationAwareBeanPostProcessor.postProcessPropertyValue()
Method, the main character of this step isAutowiredAnnotationBeanPostProcessor
andCommonAnnotationBeanPostBeanPostProcessor
They will be cached according to the precedinginjectionMetadataCache
Annotated information in the - The execution of the
populateBean()
Method, and then execute backinitializeBean()
Method, that is, enter the initialization phase. ininitializeBean()
Method is executed firstinvokeAwareMethods()
Method, that is, executionAware
Interface methods, such as:BeanNameAware
,BeanClassLoaderAware
,BeanFactoryAware
. And then execute everything againBean
Rear-processorBeanPostProcessor.postProcessBeforeInitialization()
Methods. Then performinvokeInitMethods()
Methods,invokeInitMethods()
Method is executedInitializingBean
theafterPropertiesSet()
Methods, and definitionsbean
Is custominitMethod()
Methods. One last timebean
Rear processor,BeanPostProcessor.postProcessAfterInitialization()
. - At this point
bean
The instantiation and initialization of thebean
Will be returned if it is a singletonbean
And will eventually be stored inDefaultSingletonBeanRegistry
thesingletonObjects
In the.
6.8 finishRefresh ()
- At this point,
Spring
The startup of the container is almost completeBean
Has been instantiated and the autowiring is complete. performfinishRefresh()
The method is for the containerrefresh()
At the end, do something else, such as publishContextRefreshedEvent
Event so when we want to in the containerrefresh
When you’re done, perform some special logic, and you can pass a listenerContextRefreshedEvent
Event to implement.Spring
Built-in four and application contexts (ApplicationContextEvent
) Related events:ContextRefreshedEvent
,ContextStartedEvent
,ContextStopedEvent
,ContextClosedEvent
.
protected void finishRefresh(a) {
clearResourceCaches();
initLifecycleProcessor();
getLifecycleProcessor().onRefresh();
/ / release ContextRefreshedEvent
publishEvent(new ContextRefreshedEvent(this));
LiveBeansView.registerApplicationContext(this˛);
}
Copy the code
6.9 resetCommonCaches ()
Finally, the resetCommonCaches() method is executed in the finally block of the Refresh () method. Because the singleton bean’s metadata information was cached when the bean was created, and the singleton bean is not created after the container starts, the cached information is no longer useful, so it is cleared here to free up some memory.
protected void resetCommonCaches(a) {
ReflectionUtils.clearCache();
AnnotationUtils.clearCache();
ResolvableType.clearCache();
CachedIntrospectionResults.clearClassLoader(getClassLoader());
}
Copy the code
7. Bean life cycle
- From the above
Spring
Source code analysis, it can be seen that during the startup process,bean
Is the most complex, with a total of eight callsBeanPostPorcessor
(As a matter of factbean
Over the life cycle of the9
The ninth call to the post-processor occurs inbean
Destruction phase.) - In combination with
Spring
Source code, singletonbean
The life cycle of can be summarized in the following figure
8. To summarize
- This article introduces
Spring
The startup process goes throughAnnotationConfigApplicationContext
The parametric construction method is analyzed in detailthis()
Methods andrefresh()
Methods. inthis()
An initializer is initialized inBeanFactory
, i.e.,DefaultListableBeanFactory
; We then added seven built-in ones to the containerbean
, includingConfigurationClassPostProcessor
. - in
refresh()
Methods, and focus on the analysisinvokeBeanFactoryPostProcessor()
Methods andfinishBeanFactoryInitialization()
Methods. - in
invokeBeanFactoryPostProcessor()
Method, throughConfigurationClassPostProcessor
Class scans out all handedSpring
Manage the class and willclass
The file is parsed into the correspondingBeanDefinition
. - in
finishBeanFactoryInitialization()
Method completes the singleton of non-lazy loadingBean
The main process of instantiation and initialization isgetBean()
— >doGetBean()
— >createBean()
— >doCreateBean()
. inbean
During the creation process, a total of8
timeBeanPostProcessor
In the execution of these post-processors, the execution is completedAOP
The implementation of,bean
Automatic assembly, attribute assignment and other operations. - Finally, through a flow chart, summed up
Spring
The singletonBean
Life cycle of.
Plan 9.
This article mainly introduces the Spring startup process, but there are some specific implementation details are not analyzed, so the following Spring source analysis plan is as follows:
-
ConfigurationClassPostProcessor
Class how to scan packages and resolve configuration classes. -
@Import
Annotation and@Enable
The implementation principle of series annotations -
JDK
Dynamic proxy andCGLIB
The agent -
FactoryBean
Use and source code analysis -
AutowiredAnnotationBeanPostProcessor
,CommonAnnotationBeanPostProcessor
How to achieve automatic assembly,Spring
How do I solve circular dependencies -
AOP
Implementation principle of -
SpringBoot
Source code analysis
10. Performance monitoring tools are recommended
- Finally, I recommend an open source performance monitoring tool
Pepper-Metrics
Address: github.com/zrbcool/pep… Making Pepper – Metrics is sitting opposite me two colleagues together with the development of open source components, main function is through comparing the lightweight way and the commonly used open source components (jedis/mybatis/motan/dubbo/servlet) integration, collect and calculate Metrics, It also supports output to logs and conversion to a variety of timing database compatible data formats, and the accompanying Grafana Dashboard is friendly to display. The principle of the project is fully documented, and all extensible architecture based on SPI design, convenient to develop new plug-ins. Otherwise a docker – compose based independent demo project can jumpstart a demo sample at https://github.com/zrbcool/pepper-metrics-demo. If you think it is useful, please give a star, welcome to participate in the development, thank you 🙂
Welcome to scan the qr code below, follow the wechat public number: rookie fei ya Fei read more source code, no longer for search engine programming