SpringIOC initialization process – complete Bean initialization (finishBeanFactoryInitialization)
Have explained the * * in the previous invokeBeanFactoryPostProcessors (the beanFactory); * * method; Let’s see what else we can do
@Override
public void refresh(a) throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
// Preparations include setting the startup time, whether to activate the identifier bit,
// Initialize the property source configuration
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// Return a factory
// Because the factory needs to be initialized
/ * * explain here: if the way you use yes XML configuration is executed AbstractRefreshableApplicationContext refreshBeanFactory method to load the XML configuration information; Because ClassPathXmlApplicationContext is a subclass of it; So now we are using the annotation configuration way will perform GenericApplicationContext refreshBeanFactory method, this method is the only return a the beanFactory * * /
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// Prepare the factory
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// This method does not use any code in the current version of Spring
// Perhaps Spring expects this to be extended in a later release
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
// Execute the registered Factory Processors in spring's environment
ProcessBeanFactory is set to execute custom ProcessBeanFactory and spring's own
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
/ / register beanPostProcessor
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
// Initialize the MessageSource of the current ApplicationContext
initMessageSource();
// Initialize event multicaster for this context.
// Initializes the application event broadcaster
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
// A typical template method (hook method),
// Specific subclasses can initialize special beans here (before initializing Singleton beans)
onRefresh();
// Check for listener beans and register them.
// Register event listeners that implement the ApplicationListener interface. That's not what we're talking about. Go
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
// Point, point, point
// Initialize all Singleton beans
// (except lazy-init)
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
// Finally, the event is broadcast and the ApplicationContext initialization is complete
finishRefresh();
}
/ /...
Copy the code
Internationalization, initializing application event broadcasters, and registering event listeners won’t be covered here, otherwise it’s really endless; Let’s focus on initializing all singleton Beans methods;
Initialize all the singleton beans – finishBeanFactoryInitialization (the beanFactory);
**finishBeanFactoryInitialization(beanFactory); ** method beans that are not lazily loaded are initialized here;
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// First, initialize the Bean named conversionService. That's not the point
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));
}
// Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
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);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
/ / here will beanDefinitionNames assignment to frozenBeanDefinitionNames
At this point,Spring has preinitialized the Singleton beans.
// No more bean definitions can be parsed, loaded, or registered;
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
// Instantiate all singleton objects
beanFactory.preInstantiateSingletons();
}
Copy the code
The focus is on preInstantiateSingletons (); Methods:
public void preInstantiateSingletons(a) throws BeansException {
if (logger.isDebugEnabled()) {
logger.debug("Pre-instantiating singletons in " + this);
}
// The names of all beans
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
// Triggers the initialization of all non-lazy loaded singleton beans by calling getBean
for (String beanName : beanNames) {
// Merge parent BeanDefinition
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// Whether it is an abstract class, whether it is a singleton, whether it is lazy loading
if(! bd.isAbstract() && bd.isSingleton() && ! bd.isLazyInit()) {// Whether a FactoryBean is a FactoryBean is a definite no. A future article will cover the difference between a FactoryBean and a BeanFactory
if (isFactoryBean(beanName)) {
// If it is a FactoryBean, add &
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) { getBean(beanName); }}}else {
// No FactoryBean goes directly to this methodgetBean(beanName); }}}// All non-lazy-loaded Singleton Beans have been initialized
/ / if we define the bean is realized SmartInitializingSingleton interface, so get back here, ignored
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
Focus on the getBean(beanName) method; And the initialization process is encapsulated in this method.
public Object getBean(String name) throws BeansException {
return doGetBean(name, null.null.false);
}
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
/** * Get beanName by name. There are two reasons for not using name directly as beanName *. 1. Name may start with an & character, indicating that the caller wants to get the FactoryBean itself, not the bean created by the FactoryBean * implementation class. In BeanFactory, the implementation class of a FactoryBean is the same as that of any other bean, that is,
. BeanName does not contain the & character. So we need * to remove the first character & of name to get a traditional Bean * 2, or alias problem, the conversion needs * &beanName */
,>
final String beanName = transformedBeanName(name);
// This is the return value
Object bean;
/** * This method is called on initialization, and also on getBean * why do we need to do this? * This means that spring gets the object when it is initialized * determines whether the object is instantiated * calls at initialization usually return null */
Object sharedInstance = getSingleton(beanName);
if(sharedInstance ! =null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
//log.....
}
else {
//log.....}}/** * If sharedInstance is a normal singleton bean, the following method returns it directly. But if * sharedInstance is of type FactoryBean, you call the getObject factory method to get the real * Bean instance. If the user wants to get the FactoryBean itself, nothing special is done here, just return *. After all, the implementation class of a FactoryBean is itself a bean, but with a bit of special functionality. * /
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Check if the prototype bean is being created and throw an exception if it is already being created
// Is stuck in a circular dependency
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if the Bean Definition exists in the factory
BeanFactory parentBeanFactory = getParentBeanFactory();//null
if(parentBeanFactory ! =null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
// If the BeanDefinition does not exist in the current container, try to find one in the parent container
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
//args is null passed from above
else if(args ! =null) {
// Returns the query result of the parent container
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to the standard getBean method.
returnparentBeanFactory.getBean(nameToLookup, requiredType); }}// Since parentBeanFactory==null above, the code comes here
if(! typeCheckOnly) {// Add beanName to the alreadyCreated Set
markBeanAsCreated(beanName);
}
/* * To summarize a bit: * At this point, we are ready to create the Bean, which has not been created in the container for singleton's Bean; For prototype beans, the original idea is to create a new Bean. * /
try {
// Get beanName's corresponding GenericBeanDefinition from the container and convert it to RootBeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// Check the given merged BeanDefinition
checkMergedBeanDefinition(mbd, beanName, args);
// Check dependes-on
// Initialize all dependent beans first
// Note that dependency refers to dependence as defined in Depends -on
String[] dependsOn = mbd.getDependsOn();
if(dependsOn ! =null) {
// Get the depends-on attribute value. If the depends-on value exists, add it to the dependentBeanMap cache
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw newBeanCreationException(....) ; }// Register dependencies
registerDependentBean(dep, beanName);
try {
// Initialize the dependents first
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw newBeanCreationException(...) ; }}}// Create the bean instance.
if (mbd.isSingleton()) {
//jdk1.8 Lambda expression, which calls getObject from getSingleton;
sharedInstance = getSingleton(beanName, () -> {
try {
// Perform the create Bean
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throwex; }}); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); }// If prototype scope, create prototype instance
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
// Perform the create Bean
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
// If not singleton and Prototype, delegate to the corresponding implementation class
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 {
// Perform the create Bean
return createBean(beanName, mbd, args);
}
finally{ afterPrototypeCreation(beanName); }}); bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); }catch (IllegalStateException ex) {
throw newBeanCreationException(...) . }}}catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throwex; }}// Finally, check to see if the type is correct. If not, throw an exception, if not, return an exception.
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) {
if (logger.isDebugEnabled()) {
//log....
}
throw newBeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); }}return (T) bean;
}
Copy the code
GetSingleton (); jdk1.8 getSingleton(); The getObject() method is called in this method; Enter the getSingleton() method for a quick look:
public Object getSingleton(String beanName, ObjectFactory
singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
// Currently beanName IndexDaoImpl has not been added to singletonObjects, so null
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// Check if it is being destroyed and throw an exception if it is
if (this.singletonsCurrentlyInDestruction) {
throw newBeanCreationNotAllowedException(.....) ; }//log.....
/ * * * will be added to singletonsCurrentlyInCreation beanName such a set in the collection * said beanName corresponding bean is creating in the * /
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
// Call the getObject() method, which calls the createBean() in the Lambda expression above.
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
/ /...
throw ex;
}
catch (BeanCreationException ex) {
/ /...
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
// Remove the identifier as being created
afterSingletonCreation(beanName);
}
if (newSingleton) {
// Add data to the collection
/** * protected void addSingleton(String beanName, Object singletonObject) { * synchronized (this.singletonObjects) { * this.singletonObjects.put(beanName, singletonObject); * this.singletonFactories.remove(beanName); * this.earlySingletonObjects.remove(beanName); * this.registeredSingletons.add(beanName); *} * /addSingleton(beanName, singletonObject); }}returnsingletonObject; }}Copy the code
Now let’s look at the getObject() method, and the comment says that in getObject() we’re actually calling createBean()
Let’s focus on the createBean() method;
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])
Copy the code
The third parameter, the args array, represents the parameters needed to create the instance, either for the constructor or for the factory Bean, but note that during our initialization phase, args is null.
Look at the name of the class, we come to a new kind of AbstractAutowireCapableBeanFactory, mainly to the @autowired annotation into property values
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure the Class in BeanDefinition is loadedClass<? > resolvedClass = resolveBeanClass(mbd, beanName);if(resolvedClass ! =null&&! mbd.hasBeanClass() && mbd.getBeanClassName() ! =null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
// Handles the lookup-method and replace-method configurations, which Spring collectively calls override method
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw newBeanDefinitionStoreException(...) ; }try {
// Apply the post-processing before the bean is initialized. If the bean returned by the post-processing is not empty, it is returned directly
// This class needs to be demonstrated in code
/ / here to perform the bean = applyBeanPostProcessorsBeforeInstantiation (targetType, beanName); Used in AOP, a proxy object can be returned
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if(bean ! =null) {
returnbean; }}catch (Throwable ex) {
throw newBeanCreationException(.....) ; }try {
/ / key
Call doCreateBean to create the bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
//log.....
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(......);
}
}
Copy the code
We continue with the doCreateBean() method:
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) {
/** * creates a bean instance and returns it wrapped in a BeanWrapper implementation class object. * createBeanInstance contains three ways to create bean instances: * 1. Create bean instances using factory methods * 2. Create bean instances using autowire by constructor * 3. Create a bean instance by using the no-argument constructor method * * If the bean configuration information is configured with lookup-method and replace-method, the bean instance is enhanced with CGLIB *. More on lookup-method and replace-method later. * /
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
finalObject bean = instanceWrapper.getWrappedInstance(); Class<? > beanType = instanceWrapper.getWrappedClass();if(beanType ! = NullBean.class) { mbd.resolvedTargetType = beanType; }/ / Suggestions to skip, involving interface: MergedBeanDefinitionPostProcessor
synchronized (mbd.postProcessingLock) {
if(! mbd.postProcessed) {try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true; }}// The following block of code is to solve the problem of loop dependency; We'll talk about that in a future article
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
//log....
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// Set properties, very important
// This step is responsible for the attribute assembly, because the previous instance was only instantiated, not set, this is set
populateBean(beanName, mbd, instanceWrapper);
// Execute the post-processor, where AOP is done
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
/ /... Omitted some unimportant code
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw newBeanCreationException(.....) ; }return exposedObject;
}
Copy the code
The above code focuses on the createBeanInstance() method;
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure the class is loadedClass<? > beanClass = resolveBeanClass(mbd, beanName);Spring allows access to non-public classes by default. * /
if(beanClass ! =null&&! Modifier.isPublic(beanClass.getModifiers()) && ! mbd.isNonPublicAccessAllowed()) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: "+ beanClass.getName()); } Supplier<? > instanceSupplier = mbd.getInstanceSupplier();if(instanceSupplier ! =null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
/** ** If the factory method is not empty, then through the factory method to build bean object * this way to build bean can write a demo to try * source code does not do in-depth analysis, interested students can discuss with me privately */
if(mbd.getFactoryMethodName() ! =null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
/** * This is a Shortcut, what does it mean? * You can use Shortcut when building the same bean multiple times, * that is, you don't need to deduce which way to construct the bean each time * for example, when building the same Prototypebean multiple times, Can go the Shortcut here * resolved here and MBD constructorArgumentsResolved will be the first time in the bean instance is set in the process of *; * /
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if(mbd.resolvedConstructorOrFactoryMethod ! =null) {
resolved = true;
// If the constructor parameters are parsed, you must instantiate the constructor with a parameterautowireNecessary = mbd.constructorArgumentsResolved; }}}if (resolved) {
if (autowireNecessary) {
// Construct the bean object by means of constructor auto-assembly
return autowireConstructor(beanName, mbd, null.null);
}
else {
// through the default no-argument constructor
returninstantiateBean(beanName, mbd); }}// Candidate constructors for autowiring?
// It is up to the post-processor to decide which constructors to returnConstructor<? >[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);if(ctors ! =null|| mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || ! ObjectUtils.isEmpty(args)) {return autowireConstructor(beanName, mbd, ctors, args);
}
// No special handling: simply use no-arg constructor.
// Use the default no-argument constructor for initialization
return instantiateBean(beanName, mbd);
}
Copy the code
Let’s see how a no-argument construct instantiates an object, okay
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
try {
Object beanInstance;
final BeanFactory parent = this;
if(System.getSecurityManager() ! =null) {
beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
getInstantiationStrategy().instantiate(mbd, beanName, parent),
getAccessControlContext());
}
else {
/ / getInstantiationStrategy class instantiation strategy ()
// The default is to get a reflected instantiation policy
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
// Wrap it up for return
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex); }}Copy the code
The key codes are:
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
After getting the reflected instantiation policy, go to the Instantiate method:
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
// Check whether lookup-method or replace-method is configured in the bean configuration
// If configured, use CGLIB to build bean objects
if(! bd.hasMethodOverrides()) { Constructor<? > constructorToUse;synchronized(bd.constructorArgumentLock) { constructorToUse = (Constructor<? >) bd.resolvedConstructorOrFactoryMethod;if (constructorToUse == null) {
finalClass<? > clazz = bd.getBeanClass();if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
if(System.getSecurityManager() ! =null) { constructorToUse = AccessController.doPrivileged( (PrivilegedExceptionAction<Constructor<? >>) clazz::getDeclaredConstructor); }else {
// Get a no-parameter construct
constructorToUse = clazz.getDeclaredConstructor();
}
/ / to resolvedConstructorOrFactoryMethod assigned values here
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex); }}}/ / instantiate
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// Must generate CGLIB subclass.
returninstantiateWithMethodInjection(bd, beanName, owner); }}Copy the code
Go to the instantiateClass method to instantiate:
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
Assert.notNull(ctor, "Constructor must not be null");
try {
// Set the constructor to accessible
ReflectionUtils.makeAccessible(ctor);
// reflection creates objects
return (KotlinDetector.isKotlinType(ctor.getDeclaringClass()) ?
KotlinDelegate.instantiateClass(ctor, args) : ctor.newInstance(args));
}
Copy the code
Here it’s easy to instantiate using reflection Ctor.newinstance (args); Here we take the instantiated Bean and return it to:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
To set properties and handle dependencies
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
// All the attributes of the bean instance are there
PropertyValues pvs = mbd.getPropertyValues();
if (bw == null) {
if(! pvs.isEmpty()) {throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return; }}// At this point, the bean has been instantiated (through the factory method or constructor), but the property setting has not started yet,
/ / InstantiationAwareBeanPostProcessor implementation class can be to make state changes to your bean here,
// I haven't found a practical use for it either, so let's ignore it for now
boolean continueWithPropertyPopulation = true;
if(! mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// If false is returned, no further attribute setting is required and no further BeanPostProcessor processing is required
if(! ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation =false;
break; }}}}if(! continueWithPropertyPopulation) {return;
}
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Find all attribute values by name. If it is a bean dependency, initialize the dependent bean first. Recording dependencies
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Assemble by type. complicated
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
booleanneedsDepCheck = (mbd.getDependencyCheck() ! = RootBeanDefinition.DEPENDENCY_CHECK_NONE);if(hasInstAwareBpps || needsDepCheck) { PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
/ / there is a very useful BeanPostProcessor enter here: AutowiredAnnotationBeanPostProcessor
// Set the values of @autowired and @Value annotations. There is a lot of information here, but this article won't go into it
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return; }}}}if(needsDepCheck) { checkDependencies(beanName, mbd, filteredPds, pvs); }}// Set the property value of the bean instance
applyPropertyValues(beanName, mbd, bw, pvs);
}
Copy the code
After property injection is complete, various callbacks are handled immediately:
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if(System.getSecurityManager() ! =null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
// If the bean implements the BeanNameAware, BeanClassLoaderAware, or BeanFactoryAware interface, callback
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null| |! mbd.isSynthetic()) {// Execute the beFOR for the post-processing
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// Execute the init method in the bean's declaration cycle callback
// Or if the bean implements the InitializingBean interface, call the afterPropertiesSet() method
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw newBeanCreationException( (mbd ! =null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null| |! mbd.isSynthetic()) {// Execute the afterhandler's after method
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
Copy the code
Both callbacks to BeanPostProcessor happen here, but init-method is handled in between
So that’s the whole initialization process; Draw a diagram below explain the whole process of finishBeanFactoryInitialization method:
Because the image is a little bit big, I made it smaller, so if you don’t see the image clearly, you can pull out the address and view it in the browser;
Spring source code with Chinese annotations
Blog summary
Use blogs for better viewing