Spring——BeanFactory和FactoryBean的区别

1,489 阅读14分钟

Spring——BeanFactory和FactoryBean的区别

概述

这俩在Spring中压根就完全不一样。在一些框架和Spring融合的时候使用FactoryBean。BeanFactory在日常用到的不多,取而代之的是ApplicationContext对象。

区别

BeanFactory

BeanFactory看这个名字就知道这是一个创建bean的工厂,还记得我很早很早之前看过的一本书《Spring in Action》第一版的时候,就介绍了BeanFactory和ApplicationContext的关系。有兴趣的可以去找找这本书,第一版对Spring的核心功能说的很完整。

建议直接看官方的文档BeanFactory

他是访问Spring Bean container的顶级接口,从这个接口可以获取bean。作为一个bean来说,只要交给Spring管理,Spring就会把这个bean放在他的container里面。

FactoryBean

首先,FactoryBean是一个bean。但是他不是一个普通的bean,是可以创建对象的bean。最终的暴露给外面的是他getObject()返回的对象,并且它的这个创建的对象,不会受Spring的管理。(注入是可以注入的,这里的管理,是说不会走一个标准的Springbean的生命周期)

此外,这个接口还提供了创建这个对象是单例还是多例。他的子接口SmartFactoryBean还能提供更加详细的控制。官方文档 FactoryBean

image-20211128220356280.png

这都是他的实现类。

FactoryBean分析

image-20211128221044908.png

接口本身没有什么可说的。下面分析分析在Spring中,FactoryBean是怎么解析和使用的。

在Spring中的使用分析

从一个小例子开始

  1. FactoryBean
public class MyFirstTestFactoryBean implements SmartFactoryBean<Test> {
	@Override
	public Test getObject() throws Exception {
		Test test = new Test();
		test.setAge(12);
		test.setName("name");
		return test;
	}

	@Override
	public Class<?> getObjectType() {
		return Test.class;
	}

	@Override
	public String toString() {
		return "toString-lc";
	}
}

  1. Bean

    public class Test {
    	private String name;
    	private Integer age;
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public Integer getAge() {
    		return age;
    	}
    
    	public void setAge(Integer age) {
    		this.age = age;
    	}
    
    	@Override
    	public String toString() {
    		return "Test{" +
    				"name='" + name + '\'' +
    				", age=" + age +
    				'}';
    	}
    }
    
  2. 配置类

    public class MyFirstTestFactoryConfig {
    	@Bean(name = "testFactoryBean")
    	public MyFirstTestFactoryBean testFactoryBean(){
    		return new MyFirstTestFactoryBean();
    	}
    }
    
  3. 启动类

    public class BeanFactoryApplicationText {
    	public static void main(String[] args) {
    		AnnotationConfigApplicationContext context = null;
    		try {
    			 context = new AnnotationConfigApplicationContext(MyFirstTestFactoryConfig.class);
    			Test bean = context.getBean(Test.class);
    			System.out.println(bean);
    			MyFirstTestFactoryBean myFirstTestFactoryBean = context.getBean(MyFirstTestFactoryBean.class);
    			MyFirstTestFactoryBean myFirstTestFactoryBean1 = (MyFirstTestFactoryBean) context.getBean("&testFactoryBean");
    			MyFirstTestFactoryBean myFirstTestFactoryBean2 = (MyFirstTestFactoryBean) context.getBean("&&testFactoryBean");
    			System.out.println(myFirstTestFactoryBean==myFirstTestFactoryBean1 );
    			System.out.println(myFirstTestFactoryBean==myFirstTestFactoryBean2 );
    		}catch (Throwable e){
    			e.printStackTrace();
    		}finally {
    			assert context != null;
    			context.close();
    		}
    	}
    }
    
  4. 结果

image-20211129212846942.png

factoryBean在Spring中得解析

从preInstantiateSingletons方法开始

首先要说明,FactoryBean也是一个Bean,也会走Spring标准得创建得流程。因为Spring标准得创建Bean得流程太长了,这里就不详细得说了。具体得方法是ConfigurableListableBeanFactory接口得preInstantiateSingletons,具体得实现类是DefaultListableBeanFactory

就挑一些重点得方法分析分析。

 // 判断这个bean是否是一个FactoryBean
if (isFactoryBean(beanName)) {
                  // 在正常得bean得名字得前缀前面添加 &,这个方法很熟悉了,就会走标准得bean得创建过程。
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                  
					if (bean instanceof FactoryBean) {
                        // 
						FactoryBean<?> factory = (FactoryBean<?>) bean;
						boolean isEagerInit;
                         //这里判断当前得找个bean是否是一个SmartFactoryBean,并且SmartFactoryBean得isEagerInit是否为true,
                        // 如果为true,表示需要舒适化FactoryBean创建得Bean
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged(
									(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
									getAccessControlContext());
						}
						else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}
						if (isEagerInit) {
                             // 如果需要立即初始化,就会创建BeanFactory得需要创建得Bean
							getBean(beanName);
						}
					}
				}

针对上面得代码有几个问题

  1. 怎么判断是否是一个FactoryBean(isFactoryBean()是怎么做得?)?

    本质是通过Bean得Class来判断得,主要是通过isAssignableFrom方法来判断得,并且会设置对应得BeanDefinition.里面得isFactoryBean属性为true。但是这里面还有一些小细节.

    transformedBeanName方法。

    这个方法会获取bean得真正得名字,他会去掉FactoryBean得引用得前缀 & (在BeanFactory中,从名字得前缀上可以区分普通得bean和FactoryBean,FactoryBean得名字前面是有 & 得。)

    下面得这个方法会截取掉 名字前面得&,然后再别名得缓存得map里面,通过bean得名字获取别名,如果没有,就直接返回bean得名字。

    protected String transformedBeanName(String name) {
       return canonicalName(BeanFactoryUtils.transformedBeanName(name));
    }
    
  2. 一个FactoryBean会被作用Aware接口,init和destroy和BeanPostProcess。Bean得注入吗?

    会的,之前说过,FactoryBean虽然特殊,但是他也是一个Bean,作为一个Bean来说,他是完全由资格走标准得SpringBean得创建流程得。所以,他会得。

  3. 如果需要理解初始化,走得也是正常得获取bean得方法,从这个参数可以看到,入参还是FactoryBean得名字,怎么就能通过这个名字来获取,调用到FactoryBean里面得getObjects()方法。

    主要得方法是getBean(beanName)方法。

    第三个问题,涉及到得东西比较多,这里就不说了,再下面得章节分析。

SmartFactoryBean

在FactoryBean得基础上,增加了两个方法,

  1. isPrototype 表示当前得bean是否是一个多例
  2. isEagerInit 表示当前得这个bean是否是一个立即初始化得Bean,如果需要立即初始化,在preInstantiateSingletons方法里面创建FactoryBean得时候会将这个FactoryBean创建得Bean创建出来.
public interface SmartFactoryBean<T> extends FactoryBean<T> {

	default boolean isPrototype() {
		return false;
	}

	default boolean isEagerInit() {
		return false;
	}

}

getBean(String name)方法创建FactoryBean里面得需要创建的Bean。

全量的代码就不贴出来了,分析一下重点的代码

先获取bean的真正的名字,这一步的目的是为了处理FactoryBean和普通bean的区别,但是FactoryBean也是有bean名字的,他不会自动给这个bean加上前缀&。而是在获取的时候,通过前缀来区分。

从一级缓存中获取获取bean,如果没有,就先去创建这个bean,走一波bean的标准的创建过程。

如果已经存在,就会走getObjectForBeanInstance方法,这个方法很细节。

		// 得到bean的名字,通过上面的分析可以知道,如果前缀带有&,他会去掉,比如&testFactoryBean,得到的名字就是testFactoryBean。
       String beanName = transformedBeanName(name);
		Object bean;

		//先在一级缓存中检查是否存在,如果存在就走if里面的, 不存在就走标准的创建bean的流程了,
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			if (logger.isTraceEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
             // 注意,这个方法。很细节。
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}
   // 下面就是创建标准的创建bean的过程了。忽略掉了

getObjectForBeanInstance(重点)

要注意,这里的几个参数。

beanInstance:bean的实例

name:需要获取的bean的名字,也就是调用的名字,比如 &testFactoryBean。

beanName:经过transformedBeanName处理的bean的名字。基于上面的例子,比如testFactoryBean。

RootBeanDefinition:这个bean对应的BeanDefinition

主要功能:

通过bean名字的不同, 干不同的事情,注意这里有两个name。第一个name纯粹就是为了判断,当前你想要的是一个工厂bean还是一个普通的bean。别的在没有什么意思。

因为有FactoryBean的存在,所以,在Spring里面才有这样的写法,要是没有这个操作,两个name参数没有什么意思。

获取bean可以从bean工厂的获取,也可以从FactoryBean中获取,并且通过传递的name的不同,来区分是返回Factorybean还是普通的bean。

从代码可以看到,如果是一个&开头的beanName,就认为他获取的是factoryBean,如果当前的bean是Factorybean,下面要做的就是要从Factorybean中获取需要的bean。因为bean的来源就两个,BeanFactory和FactoryBean。

在这个里里面,肯定是要维护缓存的,比如FactoryBean名字和他能创建的Bean的映射关系,上来肯定从缓存里面查,如果没有就去创建bean,这就走到了getObjectFromFactoryBean方法里面了。

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

	    // 只是单纯的看了看,前缀是不是 &开头的,注意这里判断的name,
       // 如果是&开头,说明这次想要获取的是FactoryBean,所以,这里只是做了一个判断,设置了他的isFactoryBean属性,直接返回原来的bean的实例
		if (BeanFactoryUtils.isFactoryDereference(name)) {
			if (beanInstance instanceof NullBean) {
				return beanInstance;
			}
			if (!(beanInstance instanceof FactoryBean)) {
				throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
			}
			if (mbd != null) {
				mbd.isFactoryBean = true;
			}
			return beanInstance;
		}

		// 如果不是工厂bean直接返回好了,如果是factoryBean,就会通过FactoryBena来创建Bean的实例。
		if (!(beanInstance instanceof FactoryBean)) {
			return beanInstance;
		}

		Object object = null;
		if (mbd != null) {
			mbd.isFactoryBean = true;
		}
		else {
            //从缓存中获取bena,这个缓存,key是 工厂bean的名字,value是factoryBean创建的对象
			object = getCachedObjectForFactoryBean(beanName);
		}
        // 找到就直接返回,没有就继续,
		if (object == null) {
			// Return bean instance from factory.
			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()); // 这个表示,这个bean是否是一个合成得,所谓得合成就是不是由应用程序创建得,而是由代理,或者间接创建得
             // 这里会通过Factorybean来创建bean。
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}

getObjectFromFactoryBean(从Factorybean中创建bean)

先看入参:

factory:要创建对象的FactoryBean。

beanName:这个名字和之前的一样的含义。

shouldPostProcess:是否要应用postProcess

主要功能:

主要的功能就是从FactoryBean中创建Bean实例。具体的代码逻辑如下:

如果是单例就需要缓存下来,如果不是单例,每次都要创建。此外shouldPostProcess为true,表示需要应用beanPostProcess方法 。中间还有一些的校验。

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
    // 如果是单例,并且beanName包含在bean工厂中。
   if (factory.isSingleton() && containsSingleton(beanName)) {
        // 获取锁
      synchronized (getSingletonMutex()) {
          // 先从缓存中获取,key是beanFactory的名字,v是这个beanFactory创建的bean的名字,
         Object object = this.factoryBeanObjectCache.get(beanName);
         if (object == null) {
              // 缓存中没有,这个方法就是调用FactoryBean.getObject()方法。获取bean的实例
            object = doGetObjectFromFactoryBean(factory, beanName);
            // 再次从缓存中获取一下,如果没有,才会进行后续的postPorcess和缓存中存放值
            Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
            if (alreadyThere != null) {
               object = alreadyThere;
            }
            else {
               if (shouldPostProcess) {
                  if (isSingletonCurrentlyInCreation(beanName)) { //如果说当前得bean正在创建, 那么直接返回就好了,不用走之后得process了,因为标准得流程也是会走这个流程得
                     // Temporarily return non-post-processed object, not storing it yet..
                     return object;
                  }
                  beforeSingletonCreation(beanName);
                  try {
                     object = postProcessObjectFromFactoryBean(object, beanName); //这里引用postPorcess得时候只应用得是postProcessAfter得方法
                  }
                  catch (Throwable ex) {
                     throw new BeanCreationException(beanName,
                           "Post-processing of FactoryBean's singleton object failed", ex);
                  }
                  finally {
                     afterSingletonCreation(beanName); // 前后呼应
                  }
               }
               if (containsSingleton(beanName)) {
                   //  放缓存,这里是将真正创建的bean存在缓存里面,
                  this.factoryBeanObjectCache.put(beanName, object);
               }
            }
         }
         return object;
      }
   }
   else {
      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;
   }
}

doGetObjectFromFactoryBean(从BeanFactory中获取要创建的Bean)

	private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, 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 {
                 // 这个很简单,调用的就是BeanFactory的方法,这里就直接创建对象了
				object = factory.getObject();
			}
		}
		catch (FactoryBeanNotInitializedException ex) {
			throw new BeanCurrentlyInCreationException(beanName, ex.toString());
		}
		catch (Throwable ex) {
			throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
		}

		
		if (object == null) {
			if (isSingletonCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(
						beanName, "FactoryBean which is currently in creation returned null from getObject");
			}
			object = new NullBean();
		}
		return object;
	}

到这里,已经分析了FactoryBean创建对象的几个重点的方法,上面方法的入口是假设 一个SmartFactoryBean需要立即初始化,在preInstantiateSingletons里面循环的时候创建的。下面从正常的ApplicationContext启动起来,获取bean的操作来看,他是怎么创建的。

从正常的BeanFactory#<T> T getBean(Class<T> requiredType)方法开始

通过上面的方法知道了,可以通过getBean(factoryBean(这个名字没有带&))来获取这个FactoryBean创建对象的流程了,在这个方法里面要思考一个问题怎么把FactoryBean的类型和要创建的bean的类型关联起来。只要能关联起来,就能通过走上面的逻辑来获取要创建的Bean了。

一切的开始都是从getBean(Class type)开始。

resolveNamedBean

这个方法主要是通过类型,参数来获取bean的实例,并且将bean的实例包装成NamedBeanHolder。

主要调用的方法是getBeanNamesForType(requiredType),这个方法主要是获取通过Bean的类型来获取合适的bean,并且返回合格的Bean的名字。

但是这个可能回返回多个bean的,比如一个接口的多个实现类,都是满足getBeanNamesForType条件,但是这个接口返回的是一个Bean,所以下面的都是来针对这个情况来做处理的。

如果有多个满足的Bean,就需要处理了,

先看这个bean是否有BeanDefintion,或者这个bean是否是一个Autowire的候选者,(isAutowireCandidate这个属性是BeanDefinition的属性),取值是标注了@Autowire的bean的类型的所有的实现类。组成一个新的candidateNames

只有一个,就直接返回,否则就要继续判断了。通过@Primary注解和@Priority注解来判断,如果有多个实现了这俩注解中其中之一的注解,回直接报错,通过这个处理,如果还有,就看nonUniqueAsNull的true还是false了,否则就直接返回null。

	private <T> NamedBeanHolder<T> resolveNamedBean(
			ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) throws BeansException {

		Assert.notNull(requiredType, "Required type must not be null");
         // 获取符合的Bean的名字的集合
		String[] candidateNames = getBeanNamesForType(requiredType);
       // 如果有多个符合的
		if (candidateNames.length > 1) {
			List<String> autowireCandidates = new ArrayList<>(candidateNames.length);
			for (String beanName : candidateNames) {
				if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
					autowireCandidates.add(beanName);
				}
			}
			if (!autowireCandidates.isEmpty()) {
				candidateNames = StringUtils.toStringArray(autowireCandidates);
			}
		}
       // 如果只有一个,那简单了,直接返回就好了
		if (candidateNames.length == 1) {
			String beanName = candidateNames[0];
			return new NamedBeanHolder<>(beanName, (T) getBean(beanName, requiredType.toClass(), args));
		}
         //经过上面的处理之后,这里还是多个符合的,就再次处理一下。
		else if (candidateNames.length > 1) {
            //首先组组装成一个map,map的key是beanName,map的value是bean的实例,
			Map<String, Object> candidates = new LinkedHashMap<>(candidateNames.length);
			for (String beanName : candidateNames) {
				if (containsSingleton(beanName) && args == null) {
					Object beanInstance = getBean(beanName);
					candidates.put(beanName, (beanInstance instanceof NullBean ? null : beanInstance));
				}
				else {
					candidates.put(beanName, getType(beanName));
				}
			}
            // 判断找到的多个bean里面是否有Primary注解,如果有多个Primary,就直接报错
			String candidateName = determinePrimaryCandidate(candidates, requiredType.toClass());
			if (candidateName == null) {
                 // 这里也是,是处理Priority注解的逻辑,和上面的一模一样,
				candidateName = determineHighestPriorityCandidate(candidates, requiredType.toClass());
			}
			if (candidateName != null) {
                // 如果找到了,就直接返回了。不用再搞别的了。直接返回
				Object beanInstance = candidates.get(candidateName);
				if (beanInstance == null || beanInstance instanceof Class) {
					beanInstance = getBean(candidateName, requiredType.toClass(), args);
				}
				return new NamedBeanHolder<>(candidateName, (T) beanInstance);
			}
            // 到这里,说明通过上面的处理,没有bean了,或者还有多个合适的bean,直接报错
            // nonUniqueAsNull的意思是是否 允许非唯一的,并且还能为null的bean。
			if (!nonUniqueAsNull) {
				throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());
			}
		}
       //直接返回null
		return null;
	}

doGetBeanNamesForType(ResolvableType type) (通过ResolvableType来获取bean的实例)

从getBeanNamesForType方法进来,就一直到这个方法了,熟悉Spring的都知道,do开头得方法才是干活的方法。下面就分析这个方法,真正的来获取Bean的操作。

先看方法的几个参数

  1. ResolvableType type:要匹配的类型。
  2. boolean includeNonSingletons:是否包含非单例的bean。
  3. boolean allowEagerInit:是否允许过早的初始化。

主要的功能

  1. 遍历,所有的beanDefintion,之前就说过,再Spring里面创建Bean有两个方式,一个是标准的Spring的创建bean的流程,一个是通过Factorybean,但是factoryBean又是一个Bean,所以,判断的时候要针对这种情况来做处理,此外,Spring中还有父子容器的概念,子容器是可以访问父容器的,父容器是不能访问子容器的。如果子容器中没有找到,就要去父容器中去找,此外,还有一种特殊的情况,bean的是一个未知的Bean,比如,这个bean是不是一个FactoryBean,但是他的类型确实一个NullBean,针对这个情况,要做判断,所以,Spring提供了SmartInstantiationAwareBeanPostProcessor#predictBeanType方法来判断bean的类型
  2. 大体的功能就是上面所说的那样,代码途中就是增加了一些额外的功能, 并且在Spring中,代码复用的很多,所以,一个方法看起来复杂,是因为他里面兼容了好几个地方的调用。
  3. 还需要注意的是,循环检查bean的时候,如果是Factorybean,要检查FactoryBean创建的bean的类型,如果类型不匹配,还要检查FactoryBean,(他也是一个Bean)。
private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
		List<String> result = new ArrayList<>();

		// Check all bean definitions.
		for (String beanName : this.beanDefinitionNames) {
			// Only consider bean as eligible if the bean name is not defined as alias for some other bean.
			if (!isAlias(beanName)) {
				try { 
                    // 得到BeanDefintion,
					RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				 
					if (!mbd.isAbstract() && (allowEagerInit ||
							(mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading()) &&
									!requiresEagerInitForType(mbd.getFactoryBeanName()))) {
                         // 这里会遍历所有的bean,这个时候bean的名字就是之前注册到BeanFactory中的名字,
                         //判断这个bean是否是一个工厂bean,
						boolean isFactoryBean = isFactoryBean(beanName, mbd);  
						BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
						boolean matchFound = false;
                         // 是否允许工厂bean实例化,
                        //  containsSingleton的判是因为,factorybean创建bean,前提是他得存在把,得实例化出来吧
 						boolean allowFactoryBeanInit = (allowEagerInit || containsSingleton(beanName)); 
                        // 是否不是懒惰初始化的
						boolean isNonLazyDecorated = (dbd != null && !mbd.isLazyInit());
						if (!isFactoryBean) {
                            // 如果当前的bean不是一个FactoryBean,说明这个Bean没有创建对象的能力,所以,这里只是简单的
                            // 判断当前bean的类型就好了
							if (includeNonSingletons || isSingleton(beanName, mbd, dbd)) {
								matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
							}
						}
						else { 
							if (includeNonSingletons || isNonLazyDecorated ||
									(allowFactoryBeanInit && isSingleton(beanName, mbd, dbd))) {
                                // 这里就会调用Factorybean.getType方法来判断,
								matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
							}
                            /// 如果是factoryBean但是类型确不匹配,就检测这个工厂bean
							if (!matchFound) {
								// In case of FactoryBean, try to match FactoryBean instance itself next.
								beanName = FACTORY_BEAN_PREFIX + beanName;
								matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
							}
						}
						if (matchFound) {
							result.add(beanName);
						}
					}
				}
				catch (CannotLoadBeanClassException | BeanDefinitionStoreException ex) {
					if (allowEagerInit) {
						throw ex;
					}
					// Probably a placeholder: let's ignore it for type matching purposes.
					LogMessage message = (ex instanceof CannotLoadBeanClassException ?
							LogMessage.format("Ignoring bean class loading failure for bean '%s'", beanName) :
							LogMessage.format("Ignoring unresolvable metadata in bean definition '%s'", beanName));
					logger.trace(message, ex);
					// Register exception, in case the bean was accidentally unresolvable.
					onSuppressedException(ex);
				}
				catch (NoSuchBeanDefinitionException ex) {
					// Bean definition got removed while we were iterating -> ignore.
				}
			}
		}

		// Check manually registered singletons too.
		for (String beanName : this.manualSingletonNames) {
			try {
				// In case of FactoryBean, match object created by FactoryBean.
				if (isFactoryBean(beanName)) {
					if ((includeNonSingletons || isSingleton(beanName)) && isTypeMatch(beanName, type)) {
						result.add(beanName);
						// Match found for this bean: do not match FactoryBean itself anymore.
						continue;
					}
					// In case of FactoryBean, try to match FactoryBean itself next.
					beanName = FACTORY_BEAN_PREFIX + beanName;
				}
				// Match raw bean instance (might be raw FactoryBean).
				if (isTypeMatch(beanName, type)) {
					result.add(beanName);
				}
			}
			catch (NoSuchBeanDefinitionException ex) {
				// Shouldn't happen - probably a result of circular reference resolution...
				logger.trace(LogMessage.format(
						"Failed to check manually registered singleton with name '%s'", beanName), ex);
			}
		}
		return StringUtils.toStringArray(result);
	}

大体的分析就是上面的这个样子了, 这个途中,有好几个缓存。

  1. 需要获的的bean的类型和合理的bean名字的映射map。
  2. 对于FactoryBean来说,有一个factoryBean和需要创建的bean的映射缓存。但是这个情况,只是针对FactoryBean创建单例对象。如果是多例每次都创建,并且不会应用任何的PostProcess。那么这个对象就完全和容器没有关系了。如果是单例来说,还有一点点的关系,比如如果这个Bean实现了Listener,还能被探测到。

一个问题

如果有两个FactoryBean都生产同一个类型的Bean,会怎么样?

会直接报错,。

image-20211201180047209.png 想想上面的代码逻辑,如果找到了两个合适的bean,并且这个两个合适的bean,还没有Primary或者Priority的注解,就会走到这个判断,然后通过 nonUniqueAsNull来判断是否要报错。

通过FactoryBean的机智,就能将一个没有经过标准的Spring生命周期的bean,居然可以通过Spring中的FactoryBean获取到,体现在代码就是getBean方法。那么这样做的好处是什么呢?为什么要这么做呢?

囿于篇幅,关于在Spring中,FactoryBean的具体的使用,之后再说。

关于博客这件事,我是把它当做我的笔记,里面有很多的内容反映了我思考的过程,因为思维有限,不免有些内容有出入,如果有问题,欢迎指出。一同探讨。谢谢。