[Spring source code: FactoryBean II] Finally understand how FactoryBean customizes the bean creation process

introduction

In the previous article , we focused on analyzing the flow of the getObjectType method in FactoryBean , and finally drew a general flow chart, describing the relationship between the class type we passed in (IOrderService.calss) and our custom FactoryBean subclass How to connect, that is, we call getBean(IOrderService.class) , and the bottom layer will eventually call factoryBean.getObjectType() .

In this article, we will analyze how FactoryBean allows the Spring container to manage the beans generated by calling its getObject() , and then the follow-up analysis of the previous article (as shown below):

DefaultListableBeanFactory # resolveNamedBean

At this time, some of the variable values ​​are as follows:

  • requiredType:IOrderService.class
  • candidateNames:{“orderFactoryBean”}

Because the length of the candidateNames array is 1, it will enter the getBean(beanName, requiredType, args) method, this method calls the doGetBean method, doGetBean is a very important part of the Spring container initialization, but here will not go to analyze too much Spring Bean life The content of the cycle, we only focus on the content related to FactoryBean in this article.

AbstractBeanFactory # doGetBean  (some irrelevant code omitted)

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

        //转换传入的BeanName的值,如&name变为name 以及别名(alias)的转换
		final String beanName = transformedBeanName(name);
		Object bean;

		// Eagerly check singleton cache for manually registered singletons.
        //调用getSingleton方法 从Spring容器中获取单例Bean,下面再具体分析此方法
        //这里的beanName为orderFactoryBean,获取到的是它对应的OrderFactoryBean实例(因为我们有添加@Component注解,spring容器中已创建该bean)
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {

            //这里是根据获取到的OrderFactoryBean实例本身去获取对象
            //注意这里传入了name和转换后的beanName
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

 DefaultSingletonBeanRegistry # getSingleton , get the singleton bean from the Spring container

	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        //先从singletonObjects单例池(一级缓存)中获取Bean,singletonObjects是一个ConcurrentHashMap
        //key是beanName value是单例Bean		
        Object singletonObject = this.singletonObjects.get(beanName);
		//如果单例池中不存在,并且是当前正在创建中的Bean
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            // 加锁
			synchronized (this.singletonObjects) {
                //从二级缓存中获取早期的bean
				singletonObject = this.earlySingletonObjects.get(beanName);
                //如果没有获取到,并且允许提前引用相应的Bean(依赖注入)
				if (singletonObject == null && allowEarlyReference) {
                    //singletonFactories俗称三级缓存,key:beanName,value:ObjectFactory
                    // 这个ObjectFactory是一个函数式接口,所以支持Lambda表达式:() -> getEarlyBeanReference(beanName, mbd, bean)
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
                        //从ObjectFactory中获取Bean实例
						singletonObject = singletonFactory.getObject();
                        //放入earlySingletonObjects这个Map二级缓存中,依赖注入时用到
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

This method is very important and involves the three-level cache in the Spring container:

  • Level 1 cache : singletonObjects , which caches bean objects that have gone through a complete life cycle.
  • Second-level cache : earlySingletonObjects , one more early than singletonObjects, indicates that the cached bean object is the early bean object (or: the proxy object obtained after the cache takes the original object for AOP in advance ). What does early mean? Indicates that the Bean's life cycle has not been completed before the Bean is put into earlySingletonObjects.
  • Three-level cache : singletonFactories , the cache is ObjectFactory, which represents an object factory, used to create an object.

The second level cache is mainly used to solve the circular dependency in Spring. SingletonFactories is mainly used to generate the original object and the proxy object obtained after AOP. For details, please refer to "[Interview Question] Finally someone can explain the circular dependency of Spring clearly " , well written.

Let’s return to the topic below, and then analyze AbstractBeanFactorygetObjectForBeanInstance

	protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

        // 如果传进来的OrderFactoryBean不属于FactoryBean的实例,则直接返回当前实例(表示它是普通的bean)
		if (!(beanInstance instanceof FactoryBean)) {
			return beanInstance;
		}
        
        // 如果是FactoryBean子类bean
		Object object = null;
		if (mbd != null) {
			mbd.isFactoryBean = true;
		}
		else {// 缓存中获取
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			// Return bean instance from factory.
            //如果能走到这里来,说明这个bean实例是FactoryBean类型的
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			// Caches object obtained from FactoryBean if it is a singleton.
			if (mbd == null && containsBeanDefinition(beanName)) {
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			boolean synthetic = (mbd != null && mbd.isSynthetic());
            // 从该方法名字看出:从FactoryBean中获取对象,下面再具体分析
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}

分析 FactoryBeanRegistrySupport # getObjectFromFactoryBean

	protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {

        //FactoryBean类型的实例是否单例
		if (factory.isSingleton() && containsSingleton(beanName)) {
			synchronized (getSingletonMutex()) {
                //从缓存中获取
				Object object = this.factoryBeanObjectCache.get(beanName);
				if (object == null) {

                    //缓存获取不到,则调用doGetObjectFromFactoryBean方法从FactoryBean中获取bean对象
                    //这里是调用的FactoryBean的getObject方法来获取的,具体看这一步
					object = doGetObjectFromFactoryBean(factory, beanName);
					// Only post-process and store if not put there already during getObject() call above
					// (e.g. because of circular reference processing triggered by custom getBean calls)
                    //再从缓存中获取一次
					Object alreadyThere = this.factoryBeanObjectCache.get(beanName);

                    //如果上一步的缓存中获取到了,则用缓存中的替代FactoryBean中获取的bean
					if (alreadyThere != null) {
						object = alreadyThere;
					}
					else {
						if (shouldPostProcess) {
							if (isSingletonCurrentlyInCreation(beanName)) {
								// Temporarily return non-post-processed object, not storing it yet..
								return object;
							}
							beforeSingletonCreation(beanName);
							try {
                                //调用BeanPostProcessor中的postProcessAfterInitialization方法进行处理
								object = postProcessObjectFromFactoryBean(object, beanName);
							}
							catch (Throwable ex) {
								throw new BeanCreationException(beanName,
										"Post-processing of FactoryBean's singleton object failed", ex);
							}
							finally {
								afterSingletonCreation(beanName);
							}
						}
						if (containsSingleton(beanName)) {
                            //添加到factoryBeanObjectCache中缓存,key为beanName
							this.factoryBeanObjectCache.put(beanName, object);
						}
					}
				}
				return object;
			}
		}
		else {
            //FactoryBean的实例非单例情况
			Object object = doGetObjectFromFactoryBean(factory, beanName);
			if (shouldPostProcess) {
				try {
					object = postProcessObjectFromFactoryBean(object, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
				}
			}
			return object;
		}
	}

Analyze doGetObjectFromFactoryBean , here is the getObject method of FactoryBean called to get the object

	private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
			throws BeanCreationException {

		Object object;
		try {
			if (System.getSecurityManager() != null) {
				AccessControlContext acc = getAccessControlContext();
				try {
					object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
                // 终于看到了FactoryBean中的getObject(),真相大白
				object = factory.getObject();
			}
		}

		return object;
	}

Rough flowchart ( quoted )

to sum up

Rough process: According to the class type we passed in, loop all the BeanNames in the Spring container, and then obtain the corresponding Bean instance according to the beanName, and determine whether the obtained Bean instance is a Bean of the FactoryBean type; if it is, call the getObjectType method of FactoyBean Obtain the Class, and match the obtained Class with the passed-in Class; if it matches, establish a mapping relationship between this beanName and the passed-in Class. Then obtain the corresponding FactoryBean instance bean in the Spring container according to the beanName, and call the getObject method of the FactoryBean to obtain the custom bean in our method.

Reference: https://conan.blog.csdn.net/article/details/79588391

●The strongest Tomcat8 performance optimization in history

Why can Alibaba resist 10 billion in 90 seconds? --The evolution of server-side high-concurrency distributed architecture

B2B e-commerce platform--ChinaPay UnionPay electronic payment function

Learn Zookeeper distributed lock, let interviewers look at you with admiration

SpringCloud e-commerce spike microservice-Redisson distributed lock solution

Check out more good articles, enter the official account--please me--excellent in the past

A deep and soulful public account 0.0

Guess you like

Origin blog.csdn.net/a1036645146/article/details/111736852