Previous portal:
- Pre-launch process for Spring source analysis
- BeanFactory Architecture for Spring source analysis
- Spring source analysis of BeanFactoryPostProcessor call process in detail
Content of this article:
- In IOC, how can a bean be created with defiance?
- What is the role of each BeanPostProcessor in this process, and when is it called?
Without further ado, let’s get to the point. Picture above!
Below is a general flow chart of the bean creation process. This article will analyze the source code step by step in the sequence shown in the figure
The original vector diagram address: www.processon.com/view/link/5…
As we know, there are a number of BeanPostProcessors registered in the early part of Spring IOC that will be used during Bean creation, as listed below
-
When AutowiredAnnotationBeanPostProcessor: in the new AnnotatedBeanDefinitionReader registration
-
When CommonAnnotationBeanPostProcessor: in the new AnnotatedBeanDefinitionReader registration
-
ApplicationContextAwareProcessor: when prepareBeanFactory register
-
ApplicationListenerDetector: when prepareBeanFactory register
-
ImportAwareBeanPostProcessor: in the configuration class call postProcessBeanFactory registered post processor
-
BeanPostProcessorChecker: when registerBeanPostProcessors register
That’s all the BeanPostProcessors built into Spring
Again, let’s start our analysis with the original entry refresh
public void refresh(a){
/ /... Omit the preceding part
// Instantiate the remaining singleton beans
finishBeanFactoryInitialization(beanFactory);
}
Copy the code
finishBeanFactoryInitialization
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory){
// Load all non-lazy-loaded beans into the container
beanFactory.preInstantiateSingletons();
}
Copy the code
Loop through all the BeanDefinitions we registered, one by one calling getBean to register with the container
public void preInstantiateSingletons(a){
// Loop through all beanDefinitions
for (String beanName : beanNames) {
// Convert beanDefinition to RootBeanDefinition
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// Is not abstract and is a singleton and is not lazily loaded
if(! bd.isAbstract() && bd.isSingleton() && ! bd.isLazyInit()) {// Whether it is a factory bean
if (isFactoryBean(beanName)) {
// Since the bean is retrieved starting with &, a factory bean is returned and the getObject method is not called
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
// Determine whether to initialize the bean immediatelyFactoryBean<? > factory = (FactoryBean<? >) bean;boolean isEagerInit = (factory instanceofSmartFactoryBean && ((SmartFactoryBean<? >) factory).isEagerInit());if (isEagerInit) {
// Get it again as an &, which calls the FactoryBean getObject() methodgetBean(beanName); }}}else {
// Instead of a FactoryBean, use getBean to initialize it directlygetBean(beanName); }}}}Copy the code
Next comes the usual Spring action of calling the doGetBean starting with do
public Object getBean(String name) throws BeansException {
return doGetBean(name, null.null.false);
}
Copy the code
Here is the logic for getting a singleton bean in doGetBean
// Convert beanName to remove it if it begins with & and to get an alias if it has one
String beanName = transformedBeanName(name);
// Try to fetch the bean from the level 3 cache
Object sharedInstance = getSingleton(beanName);
// Whether the bean was retrieved from the cache
if(sharedInstance ! =null && args == null) {
Call getObject() of the factory class if it is a factory class and the name does not begin with &
// Otherwise return the original object
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
Copy the code
getSingleton
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
Copy the code
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// From the singleton cache pool
Object singletonObject = this.singletonObjects.get(beanName);
// Check whether the bean is being created
// If bean 2 is being created, there are two scenarios: 1. Multiple threads are creating bean 2. Cyclic dependency occurs
// If there are multiple threads, the synchronization lock is blocked here
// The problem of loop dependency is more complex and will be examined in detail in the next chapter
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// From the early object cache pool
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
// Get the singleton factory from the level 3 cacheObjectFactory<? > singletonFactory =this.singletonFactories.get(beanName);
if(singletonFactory ! =null) {
// Call the callback method to get the early bean
singletonObject = singletonFactory.getObject();
// Place the early objects in the secondary cache and remove the tertiary cache
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName); }}}}return singletonObject;
}
Copy the code
getObjectForBeanInstance
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// Determine if name begins with &, and return the FactoryBean directly
/*public static boolean isFactoryDereference(@Nullable String name) { return (name ! = null && name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)); } * /
if (BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
// Not the factory bean returns the original object directly
if(! (beanInstanceinstanceof FactoryBean)) {
return beanInstance;
}
// Try to fetch from the cache to ensure that the same bean is fetched from the factory bean multiple times
object = getCachedObjectForFactoryBean(beanName);
if (object == null) { FactoryBean<? > factory = (FactoryBean<? >) beanInstance;booleansynthetic = (mbd ! =null && mbd.isSynthetic());
// Get the object from the FactoryBeanobject = getObjectFromFactoryBean(factory, beanName, ! synthetic); }return object;
}
Copy the code
Code snippets of getObjectFromFactoryBean
protected Object getObjectFromFactoryBean(FactoryBean<? > factory, String beanName,boolean shouldPostProcess){
// Get the bean, call factoryBean getObject()
object = doGetObjectFromFactoryBean(factory, beanName);
}
Copy the code
private Object doGetObjectFromFactoryBean(FactoryBean
factory, String beanName){
object = factory.getObject();
}
Copy the code
Now that’s the logic for getting the bean from the cache and processing the FactoryBean, let’s look at the actual bean creation process
Here is the logic to follow up the doGetBean above that did not get the bean from the cache
// Create a DependsOn bean if it is marked by @dependson
String[] dependsOn = mbd.getDependsOn();
if(dependsOn ! =null) {
for(String dep : dependsOn) { registerDependentBean(dep, beanName); getBean(dep); }}/ / the singleton beans
if (mbd.isSingleton()) {
// Start creating the bean
sharedInstance = getSingleton(beanName, () -> {
// Actually create the bean
return createBean(beanName, mbd, args);
});
Call getObject() of the factory class if it is a factory class and the name does not begin with &
// Otherwise return the original object
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
Copy the code
GetSingleton, which is an overloaded method and is not the same as getting a bean from the cache
public Object getSingleton(String beanName, ObjectFactory
singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
// The bean is locked when it is created. Note that the synchronization object for this lock is the same as the synchronization object for the lock when it is fetched from the cache
synchronized (this.singletonObjects) {
// Get it from the cache again
Thread 1 is creating instance A. Thread 2 is trying to acquire instance A. thread 2 is blocked by synchronization lock
// 2. Thread 1 is created, thread 2 enters the synchronized code block, and returns directly from the cache
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// The tag is being created
beforeSingletonCreation(beanName);
boolean newSingleton = false;
try {
// Call the callback function to get the bean
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
finally {
// Clear the state
afterSingletonCreation(beanName);
}
if (newSingleton) {
// Add the created bean to the singleton cache pool and remove the secondary and tertiary cachesaddSingleton(beanName, singletonObject); }}returnsingletonObject; }}Copy the code
CreateBean, finally start creating bean
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args){
// The bean post-handler is called the first time before the bean is instantiated
// There is no implementation in Spring's built-in back processor
// A custom post-processor can be used here to abort the bean creation process
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if(bean ! =null) {
// If a custom post-processor returns a bean, the bean creation process is interrupted
return bean;
}
// Create the bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
}
Copy the code
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args){
The second call to the bean post-processor is used to get the bean's parameter constructor
instanceWrapper = createBeanInstance(beanName, mbd, args);
// Process the beanDefinition metadata information for the third time
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
// Whether to allow exposure of early objects
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
// The fourth time to get the early object
// Put the callback method that gets the earlier object into the level 3 cache
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
ByName byType @resource @value @AutoWired @inject
populateBean(beanName, mbd, instanceWrapper);
// For the seventh and eighth times, initialize
exposedObject = initializeBean(beanName, exposedObject, mbd);
// Check whether the bean has a destruction method for the ninth time. If so, register the bean in the destruction collection for use when the container is closed
registerDisposableBeanIfNecessary(beanName, bean, mbd);
// Returns the created bean
return exposedObject;
}
Copy the code
You think this is the end of it?
So let’s take a look at what the back processor is doing here, okay
Since the first call didn’t do anything, we start with the second call
createBeanInstance
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args){
/ / get beanClassClass<? > beanClass = resolveBeanClass(mbd, beanName);/ / using AutowiredAnnotationBeanPostProcessor constructor inference, find all have constructor refsConstructor<? >[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);if(ctors ! =null|| mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || ! ObjectUtils.isEmpty(args)) {// Instantiate the bean and auto-assemble it according to the parameters
return autowireConstructor(beanName, mbd, ctors, args);
}
// Call the constructor instantiated without arguments
return instantiateBean(beanName, mbd);
}
Copy the code
determineConstructorsFromBeanPostProcessors
protectedConstructor<? >[] determineConstructorsFromBeanPostProcessors(@NullableClass<? > beanClass, String beanName)throws BeansException {
if(beanClass ! =null && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
/ / only AutowiredAnnotationBeanPostProcessor has carried on the implementation, all other returns null
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
// Identify the candidate constructorConstructor<? >[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);if(ctors ! =null) {
returnctors; }}}}return null;
}
Copy the code
AutowiredAnnotationBeanPostProcessor#determineCandidateConstructors
publicConstructor<? >[] determineCandidateConstructors(Class<? > beanClass,final String beanName){
// Get all the constructors
rawCandidates = beanClass.getDeclaredConstructors();
for(Constructor<? > candidate : rawCandidates) {// Whether there is an @autowired annotationMergedAnnotation<? > ann = findAutowiredAnnotation(candidate);if(ann ! =null) {
// Whether it is necessary
boolean required = determineRequiredStatus(ann);
candidates.add(candidate);
}
else if (candidate.getParameterCount() == 0) {
// No parameter constructordefaultConstructor = candidate; }}// The candidate constructor is not empty
if(! candidates.isEmpty()) {// The candidate constructor is not null and requiredConstructor null denotes a constructor with the @autowired identifier
/ / but the required = false
if (requiredConstructor == null) {
if(defaultConstructor ! =null) {
// Add the no-parameter constructor to the candidate constructor listcandidates.add(defaultConstructor); }}// Convert the constructor in the collection to an array
candidateConstructors = candidates.toArray(newConstructor<? > [0]);
}
// If the candidate constructor is empty and there is a parameter constructor, the parameter constructor is used as the candidate constructor
else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
candidateConstructors = newConstructor<? >[] {rawCandidates[0]};
}
// Returns an array of candidate constructors
return (candidateConstructors.length > 0 ? candidateConstructors : null);
}
Copy the code
AutowireConstructor instantiates and automates assembly, extracting code snippet
protected BeanWrapper autowireConstructor(
String beanName, RootBeanDefinition mbd, @NullableConstructor<? >[] ctors,@Nullable Object[] explicitArgs) {
return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
}
Copy the code
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
@NullableConstructor<? >[] chosenCtors,@Nullable Object[] explicitArgs) {
for(Constructor<? > candidate : candidates) {// Get the type of the parameterClass<? >[] paramTypes = candidate.getParameterTypes();// Get the dependent beanargsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames..) ;// Call the instantiate method to instantiate the beanbw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse)); }}Copy the code
That is the instantiation of the bean
applyMergedBeanDefinitionPostProcessors
The third time is to parse out the attributes or methods that identify the annotations that need to be automatically assembled. The annotations mainly include @resource @Autowired @value @Inject @postconstruct @predestroy
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class
beanType, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof MergedBeanDefinitionPostProcessor) {
/ / CommonAnnotationBeanPostProcessor parsing @ PostConstruct @ PreDestroy @ the Resource
/ / AutowiredAnnotationBeanPostProcessor parsing the @autowired @ Value @ InjectMergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp; bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName); }}}Copy the code
CommonAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class
beanType, String beanName) {
/ / for InitDestroyAnnotationBeanPostProcessor parent
// Find the @postconstruct @predestroy annotation
// Used for pre-initialization processing logic in the bean's life cycle
super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
// Find the property or method metadata identified by the @resource annotation
// Store this metadata in the cache for use during the property assembly phase
InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
// Check for duplicate metadata to reprocess, such as an attribute with both @autowired and @Resource annotations
// Use only one method for injection. Since @resource is parsed first, @resource is selected
metadata.checkConfigMembers(beanDefinition);
}
Copy the code
InitDestroyAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class
beanType, String beanName) {
// Find the PostConstruct @predestroy annotation
LifecycleMetadata metadata = findLifecycleMetadata(beanType);
// reprocess
metadata.checkConfigMembers(beanDefinition);
}
Copy the code
All of the post processor is similar, the process of take CommonAnnotationBeanPostProcessor here are analyzed
Let’s start by looking at the process of finding metadata
private InjectionMetadata findResourceMetadata(String beanName, finalClass<? > clazz,@Nullable PropertyValues pvs) {
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Fetch from the cache
/ / call postProcessMergedBeanDefinition method put metadata parsing in the cache
// Fetch the metadata when calling the postProcessProperties method
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if(metadata ! =null) {
metadata.clear(pvs);
}
// Create metadata to look for attributes or methods identified by @resouce
metadata = buildResourceMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata); }}}return metadata;
}
Copy the code
buildResourceMetadata
private InjectionMetadata buildResourceMetadata(finalClass<? > clazz){
// Determine if it is a candidate class, or return the default empty metadata
// resourceAnnotationTypes are Annotation sets containing @resource @EJB @webServiceref
// We usually just use @resource
if(! AnnotationUtils.isCandidateClass(clazz, resourceAnnotationTypes)) {return InjectionMetadata.EMPTY;
}
do {
// Loop through all attributes to see if there are WebServiceRef, EJB, Resource annotations, and build metadata if there are
// doWithLocalFields takes all fields from targetClass and loops
ReflectionUtils.doWithLocalFields(targetClass, field -> {
if(webServiceRefClass ! =null && field.isAnnotationPresent(webServiceRefClass)) {
currElements.add(new WebServiceRefElement(field, field, null));
}
else if(ejbClass ! =null && field.isAnnotationPresent(ejbClass)) {
currElements.add(new EjbRefElement(field, field, null));
}
// Whether there is an @resource annotation
else if (field.isAnnotationPresent(Resource.class)) {
if (!this.ignoredResourceTypes.contains(field.getType().getName())) {
currElements.add(new ResourceElement(field, field, null)); }}});// Similar to the previous step, determine whether these annotations exist on the method
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
/ /... omit
});
// Get the parent class
targetClass = targetClass.getSuperclass();
}
// If the parent class is not Object, continue to loop through the attributes and methods in the parent class
while(targetClass ! =null&& targetClass ! = Object.class);// Encapsulates the built metadata into InjectionMetadata
return InjectionMetadata.forElements(elements, clazz);
}
Copy the code
Now let’s look at the reprocessing process
public void checkConfigMembers(RootBeanDefinition beanDefinition) {
Set<InjectedElement> checkedElements = new LinkedHashSet<>(this.injectedElements.size());
for (InjectedElement element : this.injectedElements) {
Member member = element.getMember();
/ / check if the beanDefinition externallyManagedConfigMembers set already contains the members (properties or methods)
if(! beanDefinition.isExternallyManagedConfigMember(member)) {// If it does not, the member will be registered
beanDefinition.registerExternallyManagedConfigMember(member);
// Add to the checked collectioncheckedElements.add(element); }}this.checkedElements = checkedElements;
}
Copy the code
For the fourth time, there is no implementation in Spring’s built-in processor for the call to process the earlier object, so skip it
This step, like the first, will be used with AOP and will be examined in the next chapter
The next step is to fill in the properties
populateBean
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
/ / here can be suspended filling property operation, implement InstantiationAwareBeanPostProcessor interface
/ / and postProcessAfterInstantiation returns false, the returned directly, not to perform
// All post-processors in Spring return true
if(! mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if(! ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {return; }}}}// Get the autowiring type, default is 0,
/ / here only XML configuration, ImportBeanDefinitionRegistrar, spring BeanFactoryPostProcessor can be changed
Mybatis = Mapper = BY_TYPE;
/ / in Mapper can be populated here SqlSessionTemplate, SqlSessionFactory properties
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
// Get the dependent bean and put it in newPvs
autowireByType(beanName, mbd, bw, newPvs);
}
// Assign the new attribute list to the old referencepvs = newPvs; }}Copy the code
The autowireByName is similar to the autowireByType, but the autowireByType is more complex, and only the processing of the autowireByType is analyzed here
protected void autowireByType( String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
// Query properties that are not simple (Java built-in primitive types, String,Date, etc.)
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
// Loop through all attribute names
for (String propertyName : propertyNames) {
// Get method parameters
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
// Build a dependency descriptor
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
// Get the dependent bean
// doResolveDependency is called in the resolveDependency method, which we will examine in the next post-handler call
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
// Place the bean in the property collection
if(autowiredArgument ! =null) { pvs.add(propertyName, autowiredArgument); }}}Copy the code
Now, back to the process of populating the properties
This sixth call puts the processor behind it, this time focusing on the auto-assembly of properties and methods
/ / @ Resouce CommonAnnotationBeanPostProcessor processing annotations of assembly
/ / AutowiredAnnotationBeanPostProcessor processing @autowired @ Value @ Inject annotation of assembly
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// Handles autowiring, which assembles dependent properties into beans
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
/ /... Omit deprecated code...pvs = pvsToUse; }}Copy the code
The logic of this step is about the same, due to the complexity of AutowiredAnnotationBeanPostProcessor, we take the analysis of logic of AutowiredAnnotationBeanPostProcessor
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
/ / remove before postProcessMergedBeanDefinition parsed metadata
// @autowired @value @inject Identifies an attribute or method
// findAutowiringMetadata
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
// Perform automatic assembly
metadata.inject(bean, beanName, pvs);
return pvs;
}
Copy the code
FindAutowiringMetadata, and see how much like the fourth step ~
private InjectionMetadata findAutowiringMetadata(String beanName, Class<? > clazz,@Nullable PropertyValues pvs) {
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Fetch from cache
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if(metadata ! =null) {
metadata.clear(pvs);
}
// Build metadata, find the attribute or method identified by @autowird @value @inject to build
metadata = buildAutowiringMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata); }}}return metadata;
}
Copy the code
Automatic assembly process
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) {
// Retrieve the list of metadata that was previously reworked
Collection<InjectedElement> checkedElements = this.checkedElements;
if(! elementsToIterate.isEmpty()) {for (InjectedElement element : elementsToIterate) {
// Perform attribute or method assemblyelement.inject(target, beanName, pvs); }}}Copy the code
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs){
// force Field
Field field = (Field) this.member;
// Create a dependency descriptor
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
// Get the dependent bean
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
if(value ! =null) {
ReflectionUtils.makeAccessible(field);
// Assemble the obtained dependent beans into properties using reflectionfield.set(bean, value); }}Copy the code
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {
/ / get a bean
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
return result;
}
Copy the code
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter){
// Parse @value annotations
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if(value ! =null) {
return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
}
// Find matching Beandefinitions by type
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
// If it is empty, determine whether it is necessary
if (isRequired(descriptor)) {
/ / must have thrown NoSuchBeanDefinitionException anomalies
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
// If there is more than one candidate bean matching by type, you need to confirm which one it is
if (matchingBeans.size() > 1) {
// Identify what you really need to rely on
// check if there is a @primary annotation
// The Priority annotation is not implemented
// There is no final match using the attribute name
// Return null if no match is found
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
// Check if it is necessary and throw an exception if it is
if(isRequired(descriptor) || ! indicatesMultipleBeans(type)) {return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
return null;
}
}
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
if (instanceCandidate instanceof Class) {
// Call the getBean method
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
return result;
}
Copy the code
GetBean method
public Object resolveCandidate(String beanName, Class
requiredType, BeanFactory beanFactory) {
return beanFactory.getBean(beanName);
}
Copy the code
So that’s the autowiring process, going back to the method of filling the properties for a little finishing touch
// PVS is null if it is not XML byName byType
if(pvs ! =null) {
// Call set to assign a value
applyPropertyValues(beanName, mbd, bw, pvs);
}
Copy the code
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
// Use reflection to assign values to attributes
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
Copy the code
Procedure for filling properties, over~
Initialization process
initializeBean
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd){
// If the bean implements the BeanNameAware, BeanClassLoaderAware, BeanFactoryAware interface
// call back the corresponding method
invokeAwareMethods(beanName, bean);
// The seventh time the bean is processed before initialization
// Call the @postconstruct annotation method, the Aware interface callback method
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
// Call the initialization method
// If the bean implements the InitializingBean interface, the afterPropertiesSet method is called
// Also called if the bean also implements a custom initialization method
// afterPropertiesSet, then custom
invokeInitMethods(beanName, wrappedBean, mbd);
// Process the initialized bean for the eighth time
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
Copy the code
The above is the general process of initialization, and we will analyze it one by one
The first is invokeAwareMethods
private void invokeAwareMethods(String beanName, Object bean) {
// The following process is clear at a glance, without much analysis
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if(bcl ! =null) { ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl); }}if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); }}}Copy the code
applyBeanPostProcessorsBeforeInitialization
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName){
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
/ / ImportAwareBeanPostProcessor processing ImportAware interface
/ / InitDestroyAnnotationBeanPostProcessor processing @ PostContrust annotation
/ / ApplicationContextAwareProcessor processing series of Aware interface callback methods
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
Copy the code
InitDestroyAnnotationBeanPostProcessor
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// Retrieve the metadata from the @postcontrust @predestroy parsing in step 4
LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
// call init (@postconstruct)
metadata.invokeInitMethods(bean, beanName);
return bean;
}
Copy the code
public void invokeInitMethods(Object target, String beanName) throws Throwable {
// Fetch only init metadata (and destroy metadata)
Collection<LifecycleElement> checkedInitMethods = this.checkedInitMethods;
if(! initMethodsToIterate.isEmpty()) {for(LifecycleElement element : initMethodsToIterate) { element.invoke(target); }}}Copy the code
public void invoke(Object target) throws Throwable {
ReflectionUtils.makeAccessible(this.method);
// Direct reflection calls
this.method.invoke(target, (Object[]) null);
}
Copy the code
ApplicationContextAwareProcessor process and invokeAwareMethods similar, here is not analyzed
invokeInitMethods
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd){
// If InitializingBean interface is implemented, call afterPropertiesSet method
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null| |! mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
((InitializingBean) bean).afterPropertiesSet();
}
if(mbd ! =null&& bean.getClass() ! = NullBean.class) {// Call a custom initialization method
String initMethodName = mbd.getInitMethodName();
if(StringUtils.hasLength(initMethodName) && ! (isInitializingBean &&"afterPropertiesSet".equals(initMethodName)) && ! mbd.isExternallyManagedInitMethod(initMethodName)) {// Custom init methods are declared mainly in the @bean annotation, just pull out the initMethod call from beanDefinitioninvokeCustomInitMethod(beanName, bean, mbd); }}}Copy the code
applyBeanPostProcessorsAfterInitialization
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
/ / rear Spring built-in processor, only ApplicationListenerDetector processing logic
/ / ApplicationListenerDetector will implement the interface ApplicationListener bean to add to the list of event listeners
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
Copy the code
public Object postProcessAfterInitialization(Object bean, String beanName){
if (bean instanceof ApplicationListener) {
// Add the bean to the list of event listeners
this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
}
}
Copy the code
That’s it! The bean is initialized!
With the bean initialization completed, the creation of the bean is complete, and this article is over. If you have any questions, please leave a comment below
Preview below: Loop dependencies for Spring source analysis
Spring Source code series
- Spring source code analysis of IOC container prestart process (completed)
- BeanFactory Architecture for Spring source analysis (completed)
- Spring Source Analysis BeanFactoryPostProcessor call process (completed)
- Spring source analysis Bean creation process (completed)
- What are cyclic dependencies and solutions for Spring source analysis
- AOP for Spring source analysis from parsing to invocation
- Spring source analysis of transaction management (1), transaction management is a feature of Spring as a container, summarize his basic implementation and principle
- Spring source analysis of transaction management (below), about his underlying thing isolation and thing propagation principle, focus on the analysis
Spring Mvc source code series
- The SpringMvc architecture
- SpringMvc source code analysis Handler parsing process
- Request chain process for SpringMvc source code analysis
Mybatis source series
tentative
Chase after more, can pay attention to me, recently have time to write the whole article, share pure for fun, also have a sense of achievement, the author of this article to this first