Spring 5.x Source trip seventeen getBean Detailed three

doCreateBean

Part Before the processor may return to instantiate an object, if there is no object, you'll be doCreateBeantruly create the objects. This method is very complex, we slowly run. First, the cache will first get, if you do not get to create one instance, which is a BeanWrappertype of packaging, then processor applyMergedBeanDefinitionPostProcessors, if needed to resolve circular references will be added to a singleton factory, then filled property, initialization registered destruction callback before returning. In the middle of each process is very complicated, we slowly say.

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {


		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {//获取factoryBean实例缓存
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {//没有即创建实例
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		final Object bean = instanceWrapper.getWrappedInstance();//获取原始bean
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {//不为空的bean
			mbd.resolvedTargetType = beanType;
		}
		//处理器修改合并bean定义
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					...
				}
				mbd.postProcessed = true;
			}
		}
		//暴露早期的单例,处理循环引用
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			...
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));//添加一个单例工厂方法
		}
		//进行初始化
		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			populateBean(beanName, mbd, instanceWrapper);
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
			...
		}

		if (earlySingletonExposure) {
			Object earlySingletonReference = getSingleton(beanName, false);
			if (earlySingletonReference != null) {
				if (exposedObject == bean) {
					exposedObject = earlySingletonReference;
				}
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
					String[] dependentBeans = getDependentBeans(beanName);
					Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
					for (String dependentBean : dependentBeans) {
						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
							actualDependentBeans.add(dependentBean);
						}
					}
					if (!actualDependentBeans.isEmpty()) {
						throw new BeanCurrentlyInCreationException...
					}
				}
			}
		}

		// Register bean as disposable.
		try {//注册可销毁的bean
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			...
		}

		return exposedObject;
	}

createBeanInstance create the bean instance

First get the type, then get modifiers only publicallow you to create, and then obtain an instance of a custom provider, if any, direct access to return, there is no word if there are factory method name, created by the factory method, otherwise there would Analyzing the constructor to go to find the appropriate constructor for automatic assembly, otherwise a default constructor instantiated.

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
		// Make sure bean class is actually resolved at this point.
		Class<?> beanClass = resolveBeanClass(mbd, beanName);
		//检查是public修饰的
		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 (mbd.getFactoryMethodName() != null) {
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

		// Shortcut when re-creating the same bean...
		boolean resolved = false;//标记下,防止重复创建同一个bean
		boolean autowireNecessary = false;//是否需要自动装配,构造器有参数的需要
		if (args == null) {//无参
			synchronized (mbd.constructorArgumentLock) {
				if (mbd.resolvedConstructorOrFactoryMethod != null) {//有解析的构造器或者工厂方法
					resolved = true;
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
		if (resolved) {//有构造参数的或者工厂方法
			if (autowireNecessary) {//构造器有参数的
				return autowireConstructor(beanName, mbd, null, null);
			}
			else {//无参的
				return instantiateBean(beanName, mbd);
			}
		}
		//从bean后置处理器中为自动装配寻找构造方法
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
			return autowireConstructor(beanName, mbd, ctors, args);
		}
		// 找出最合适的默认构造方法
		ctors = mbd.getPreferredConstructors();
		if (ctors != null) {
			return autowireConstructor(beanName, mbd, ctors, null);
		}
		// 最后才用最简单的默认构造方法
		return instantiateBean(beanName, mbd);
	}

Examples provider obtainFromSupplier

This is mainly the expansion of our own, we first look inside how he did, then I would be a real friends.
Mainly from a given provider in the get()method for obtaining beaninstance, and then packed into BeanWrappertypes, then initBeanWrapperinitialized.

protected BeanWrapper obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) {
		Object instance;

		String outerBean = this.currentlyCreatedBean.get();
		this.currentlyCreatedBean.set(beanName);
		try {
			instance = instanceSupplier.get();
		}
		finally {
			if (outerBean != null) {//不为空还是这是老的
				this.currentlyCreatedBean.set(outerBean);
			}
			else {//为空删除
				this.currentlyCreatedBean.remove();
			}
		}

		if (instance == null) {
			instance = new NullBean();
		}
		BeanWrapper bw = new BeanWrapperImpl(instance);
		initBeanWrapper(bw);
		return bw;
	}

InstanceSupplier actual extension points

InstanceSupplierBeanDefinitionRegistryPostProcessor

Create a post-processor, which registered a beandefinition and examples provided, providing a UserDaoImple2name is userDaoto keep MyConfigthe same method names, and can be called a processor add way .

public class InstanceSupplierBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        registry.registerBeanDefinition("userDao",new RootBeanDefinition(UserDao.class, () -> {
            System.out.println("UserDao自定义提供器");
            return new UserDaoImple2();
        }));
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    }
}

UserDaoImple2

public class UserDaoImple2 implements UserDao {
    @Override
    public void getUser() {
        System.out.println("UserDaoImple2 getUser");
    }

}

MyConfig

And the method name to the strength of the provider's beanname, but returns UserDaoImpletype.

@Configuration
public class MyConfig {
    @Bean
    public UserDao userDao(){
        return new UserDaoImple();
    }
}

test

    @Test
    public void InstanceSupplierTest0() throws Exception {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        applicationContext.register(MyConfig.class);
        applicationContext.addBeanFactoryPostProcessor(new InstanceSupplierBeanDefinitionRegistryPostProcessor());
        applicationContext.refresh();
        UserDao userDao = (UserDao)applicationContext.getBean("userDao");
        System.out.println(userDao);
        userDao = (UserDao)applicationContext.getBean("userDao");
        System.out.println(userDao);
    }

result

There's offer:
Here Insert Picture Description
free provider of:
Here Insert Picture Description

This is how it happened, we have the provider MyConfigin the method does not work it? Is, in fact, is beandefined to be covered, remember speaking in front of, configuration, the processor will MyConfigbe parsed, validated, and then load the beandefinition loading beandefined inside, there is a isOverriddenByExistingDefinitionmethod, can determine whether to overwrite the existing beandefinition of because we offer self-defined at the very beginning has been registered bean definitions, so MyConfigthe userDaotime was loaded will be judged to see whether or not to overwrite, if you do not cover the direct return, so we MyConfigin the the method of information never even registered into the beandefinition:
Here Insert Picture Description
the main judgment code is ConfigurationClassBeanDefinitionReaderthe isOverriddenByExistingDefinitionfact that there is a logic to determine, first determine the existing beandefinitions and is not beanregistered with a configuration method overloading class method, because of the same name Well, if it is then do not cover, and set up the factory method is not unique, otherwise they will be covered, if not, to see is not component scanscanned in the beandefinition, if you want to overwrite, if not to see is not internal, if it is also covered, so that we You may cover springthe internal processor it:

	protected boolean isOverriddenByExistingDefinition(BeanMethod beanMethod, String beanName) {
		if (!this.registry.containsBeanDefinition(beanName)) {
			return false;
		}
		BeanDefinition existingBeanDef = this.registry.getBeanDefinition(beanName);
		//如果是ConfigurationClassBeanDefinition类型的话,且是同一个配置类的重载方法,就保存现有
		if (existingBeanDef instanceof ConfigurationClassBeanDefinition) {
			ConfigurationClassBeanDefinition ccbd = (ConfigurationClassBeanDefinition) existingBeanDef;
			if (ccbd.getMetadata().getClassName().equals(
					beanMethod.getConfigurationClass().getMetadata().getClassName())) {
				if (ccbd.getFactoryMethodMetadata().getMethodName().equals(ccbd.getFactoryMethodName())) {
					ccbd.setNonUniqueFactoryMethodName(ccbd.getFactoryMethodMetadata().getMethodName());//设置工厂方法不唯一,说明有重载
				}
				//不覆盖
				return true;
			}
			else {
				return false;//覆盖
			}
		}
		//如果是component scan, 覆盖现有的
		if (existingBeanDef instanceof ScannedGenericBeanDefinition) {
			return false;
		}
		//如果是框架内部的,覆盖现有的

		if (existingBeanDef.getRole() > BeanDefinition.ROLE_APPLICATION) {
			return false;
		}

		//不覆盖
		return true;
	}

We draw a logic diagram:
Here Insert Picture Description
look at the springwhat happens right after the internal configuration of the default class processor changed, if changed would not have to configure the processor, MyConfigwhere beanthe definition would not be a:
Here Insert Picture Description
had say springreally flexible, extensible good, you can even change the internal processor, you can customize the processor to handle, for example, I put the processor to initialize all the coverage, and now I have the final say initialization, this scalability really strong ah:
Here Insert Picture Description
this is bad I play:
Here Insert Picture Description
finally provided a method of providing an example, the registration of the way , the same principle:

    @Test
    public void InstanceSupplierTest0()  {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        applicationContext.register(MyConfig.class);
        applicationContext.registerBean("userDao",UserDao.class,() -> {
            System.out.println("UserDao自定义提供器");
            return new UserDaoImple2();
        },null);
        applicationContext.refresh();
        UserDao userDao = (UserDao)applicationContext.getBean("userDao");
        System.out.println(userDao);
        userDao = (UserDao)applicationContext.getBean("userDao");
        System.out.println(userDao);
    }

He wrote so many, not any talk about what seems, to continue it next time.

Well, here today, we hope to help study and understand, do not spray the Great God see, understand only their own learning, limited capacity, please excuse.

Published 235 original articles · won praise 74 · views 30000 +

Guess you like

Origin blog.csdn.net/wangwei19871103/article/details/105047258