Spring bean initialization (2) - bean instantiation

Spring bean initialization (2) - bean instantiation

 

    XmlBeanFactory bf = new XmlBeanFactory(new ClassPathResource("/spring-code-test.xml"));
    // bean instantiation is triggered by getBean call
    TestBean bean = (TestBean) bf.getBean("testbean");

 The previous section talked about the first step above, loading and parsing xml. After this step is completed, the bean definition is converted into a BeanDefinition object, and the getBean method actually instantiates the BeanDefinition information.

 

Let's talk about the instantiation process

  

// AbstractBeanFactory class
public Object getBean(String name) throws BeansException {
    return doGetBean(name, null, null, false);
}

protected <T> T doGetBean(
			final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
			throws BeansException {

		final String beanName = transformedBeanName(name);
		Object bean;
        // First get the current bean, if you can get the bean object,
        // Or you can get the object returned by ObjectFactory.getObject() corresponding to the bean
        // ObjectFactory.getObject() is to solve the circular dependency problem of singleton, which will be described in detail later
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
            // Ordinary bean, this method does not process, if it is FactoryBean,
            // will actually return the object returned by FactoryBean.getObject()
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		} else {
			//Skip the current beanfactory if there is no bean, the parent beanfactory will be queried

			try {
                        // Convert beanDefinition to RootBeanDefinition, bean creation is based on RootBeanDefinition
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

				// Guarantee initialization of beans that the current bean depends on.
				
				// If the bean has not been created, start creating the bean, and actually call the getObject method in the ObjectFactory,
                                // and then call the createBean method
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
						@Override
						public Object getObject() throws BeansException {
							try {
								return createBean(beanName, mbd, args);
							}
							catch (BeansException ex) {
								destroySingleton (beanName);
								throw ex;
							}
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
                                // The prototype type does not allow circular dependencies, because it is created when used, and there is no singleton-related cache to help resolve circular dependencies
                                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);
					try {
						Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
							@Override
							public Object getObject() throws BeansException {
								beforePrototypeCreation (beanName);
								try {
									return createBean(beanName, mbd, args);
								}
								finally {
									afterPrototypeCreation (beanName);
								}
							}
						});
						bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
					}
				}
			}
		}

		// Check if required type matches the type of the actual bean instance.
		return (T) bean;
	}
  How to solve the circular dependency problem of beans in singleton mode is actually solved by caching records. Suppose A depends on B, and B depends on A. When creating an object of A, it will first instantiate A, and then put the ObjectFactory object of A into Cache the singletonFactories , then find the properties of A and inject it into B, start the creation of B, instantiate B, put the ObjectFactory object of B into the  singletonFactories , then find the dependency A, instantiate A, and enter the method getSingleton(beanNam) of the above code, At this point, the object of A in singletonFactories can be obtained . Although A has not been initialized, but the reference of A has been obtained at this time, the initialization and attribute injection of B can continue to be completed. After B is completed, the dependency injection of B and A can be continued. initialization. The code for getSingleton is as follows
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
                // Look up from the cache of bean objects that have been created, and return if found
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
                                // find from earlySingletonObjects
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
                                        // If not found, go to singletonFactories to find
                                        // The object being created will first put the ObjectFactory into the singletonFactories
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						singletonObject = singletonFactory.getObject();
                                                // Add the cache to improve the efficiency of the next visit						
                                                this.earlySingletonObjects.put(beanName, singletonObject);
                                                // These two caches are mutually exclusive, the above one is added, the following one is useless						
                                                this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return (singletonObject != NULL_OBJECT ? singletonObject : null);
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326224747&siteId=291194637