Spring源码解析(21)之bean创建流程之转换器

一、前言

        在前面的几节中我们已经介绍完refresh()的其他方法了,接下来就是finishBeanFactoryInitialization方法,初始化所有剩余的单实例Bean(没有使用懒加载的Bean).整个Spring IOC的核心,接下来我们看看这个方法到底做了哪些事情?

	protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
		// 1. 初始化此上下文的转换服务,用来自定义将Spring中的某个Bean的属性从一个类型转换到另外一个类型.
		//    判断Bean工厂中是否存在名称为conversionService的转换服务bean,如果存在而且类型为ConversionService,则获取该Bean实例,并将其设置到BeanFactory中
		/**
		 * 例如:
		 * (1)有如下的javaBean:
		 * public class Person {
		 *     public String name;
		 *     public Date birthday;
		 *     ...
		 * }
		 * (2)有如下的xml配置:
		 * <bean name="person" class="com.wb.test.Person">
		 *     <property name="name" value="wangbing"/>
		 *     <property name="birthday" value="1999-03-03"/>
		 * </bean>
		 * (3)有如下的测试类:
		 * ApplicationContext acx = new ClasspathXmlApplicationContext("test.xml");
		 * Person person = (Person) acx.getBean("person");
		 * System.out.println(person.name);
		 * System.out.println(person.birthday); // 改行会报错,提示字符串类型不能转换为日期类型
		 *
		 * (4)可以通过定义如下名称的bean,将某种类型的属性值转换为另外一种类型.
		 * <bean name="conversionService" class="com.wb.test.MyConversionService" />
		 * public class MyConversionService implements ConversionService {
		 *    // 实现是否能转换以及具体转换的方法。
		 *	  public boolean canConvert(Class<?> sourceType, Class<?> targetType) {}
		 *	  public boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType) {}
		 *    public <T> T convert(Object source, Class<T> targetType) {}
		 *    // 可以在该方法中实现转换逻辑。如果源类型sourceType是String类型的话,将其转换为Date类型返回。
		 *    public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {}
		 * }
		 */
		// 2.在Spring中,如果需要配置自定义的转换器,还可以直接利用Spring提供的ConversionServiceFactoryBean来完成。自己只需要实现具体的转换逻辑即可
		/**
		 * (1)配置conversionService对应的工厂Bean:
		 * <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
		 *     <property name="converters">
		 *			<bean class="com.wb.test.MyConverter"/>
		 *     </property>
		 * </bean>
		 * (2)然后自己去实现MyConverter即可:
		 *  public class MyConverter implements Converter<String,Date> {
		 *        @Override
		 *        public Date convert(String source) {
		 *			DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
		 *			try {
		 *				return format.parse((String) source);
		 *            } catch (ParseException e) {
		 *				e.printStackTrace();
		 *            }
		 *			return null;
		 *        }
		 *    }
		 */
		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));
		}
		/**
		 * 如果beanFactory之前没有注册嵌入值解析器,则注册默认的嵌入值解析器,
		 *  主要用于注解属性值的解析例如:@Value("${app.name}")。
		 */
		// 值解析器设置的地方:在调用invokeBeanfactoryPostProcessor方法的时候,通过PropertySourcesPlaceholderConfigurer的后置处理方法设置进去的
		if (!beanFactory.hasEmbeddedValueResolver()) {
			// 调用resolvePlaceholders方法解析strVal对应的值
			beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
		}
		/**
		 * 初始化所有实现了LoadTimeWeaverAware接口的子类,用于类在加载进入jvm之前,动态增强类
		 *  这特别适用于Spring的JPA支持,其中load-time weaving加载织入对JPA类转换非常必要
		 */
		String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
		for (String weaverAwareName : weaverAwareNames) {
			getBean(weaverAwareName);
		}

		// 停止使用临时的类加载器.
		beanFactory.setTempClassLoader(null);

		// 缓存(冻结)所有的BeanName(注册的bean定义不会被修改或进一步做处理了,因为下面马上要创建Bean的实例对象了)
		beanFactory.freezeConfiguration();

		// 初始化所有的单实例Bean,包括创建单实例bean的全部过程
		beanFactory.preInstantiateSingletons();
	}

        第一步我们首先是判断此上下文是否存在转换服务,用来自定义将Spring中的某个Bean的属性从一个类型转换到另外一个类型,判断Bean工厂中是否存在名称为conversionService的转换服务bean,如果存在而且类型为ConversionService,则获取该Bean实例,并将其设置到BeanFactory中。我们来看下对应conversionService对应的实现子类:DefaultConversionService。

public class  DefaultConversionService extends GenericConversionService {

	/** 【懒汉式单例设计模式DCL】使用volatile禁止指令重排序 */
	@Nullable
	private static volatile DefaultConversionService sharedInstance;

	/**
	 * Create a new {@code DefaultConversionService} with the set of
	 * {@linkplain DefaultConversionService#addDefaultConverters(ConverterRegistry) default converters}.
	 */
	public DefaultConversionService() {
		addDefaultConverters(this);
	}


	/**
	 * Return a shared default {@code ConversionService} instance,
	 * lazily building it once needed.
	 * <p><b>NOTE:</b> We highly recommend constructing individual
	 * {@code ConversionService} instances for customization purposes.
	 * This accessor is only meant as a fallback for code paths which
	 * need simple type coercion but cannot access a longer-lived
	 * {@code ConversionService} instance any other way.
	 * @return the shared {@code ConversionService} instance (never {@code null})
	 * @since 4.3.5
	 */
	public static ConversionService getSharedInstance() {
		DefaultConversionService cs = sharedInstance;
		if (cs == null) {
			synchronized (DefaultConversionService.class) {
				cs = sharedInstance;
				if (cs == null) {
					cs = new DefaultConversionService();
					sharedInstance = cs;
				}
			}
		}
		return cs;
	}

	/**
	 * Add converters appropriate for most environments.
	 * @param converterRegistry the registry of converters to add to
	 * (must also be castable to ConversionService, e.g. being a {@link ConfigurableConversionService})
	 * @throws ClassCastException if the given ConverterRegistry could not be cast to a ConversionService
	 */
	public static void addDefaultConverters(ConverterRegistry converterRegistry) {
		addScalarConverters(converterRegistry);
		addCollectionConverters(converterRegistry);

		converterRegistry.addConverter(new ByteBufferConverter((ConversionService) converterRegistry));
		converterRegistry.addConverter(new StringToTimeZoneConverter());
		converterRegistry.addConverter(new ZoneIdToTimeZoneConverter());
		converterRegistry.addConverter(new ZonedDateTimeToCalendarConverter());

		converterRegistry.addConverter(new ObjectToObjectConverter());
		converterRegistry.addConverter(new IdToEntityConverter((ConversionService) converterRegistry));
		converterRegistry.addConverter(new FallbackObjectToStringConverter());
		converterRegistry.addConverter(new ObjectToOptionalConverter((ConversionService) converterRegistry));
	}

	/**
	 * Add common collection converters.
	 * @param converterRegistry the registry of converters to add to
	 * (must also be castable to ConversionService, e.g. being a {@link ConfigurableConversionService})
	 * @throws ClassCastException if the given ConverterRegistry could not be cast to a ConversionService
	 * @since 4.2.3
	 */
	public static void addCollectionConverters(ConverterRegistry converterRegistry) {
		ConversionService conversionService = (ConversionService) converterRegistry;

		converterRegistry.addConverter(new ArrayToCollectionConverter(conversionService));
		converterRegistry.addConverter(new CollectionToArrayConverter(conversionService));

		converterRegistry.addConverter(new ArrayToArrayConverter(conversionService));
		converterRegistry.addConverter(new CollectionToCollectionConverter(conversionService));
		converterRegistry.addConverter(new MapToMapConverter(conversionService));

		converterRegistry.addConverter(new ArrayToStringConverter(conversionService));
		converterRegistry.addConverter(new StringToArrayConverter(conversionService));

		converterRegistry.addConverter(new ArrayToObjectConverter(conversionService));
		converterRegistry.addConverter(new ObjectToArrayConverter(conversionService));

		converterRegistry.addConverter(new CollectionToStringConverter(conversionService));
		converterRegistry.addConverter(new StringToCollectionConverter(conversionService));

		converterRegistry.addConverter(new CollectionToObjectConverter(conversionService));
		converterRegistry.addConverter(new ObjectToCollectionConverter(conversionService));

		converterRegistry.addConverter(new StreamConverter(conversionService));
	}

	private static void addScalarConverters(ConverterRegistry converterRegistry) {
		converterRegistry.addConverterFactory(new NumberToNumberConverterFactory());

		converterRegistry.addConverterFactory(new StringToNumberConverterFactory());
		converterRegistry.addConverter(Number.class, String.class, new ObjectToStringConverter());

		converterRegistry.addConverter(new StringToCharacterConverter());
		converterRegistry.addConverter(Character.class, String.class, new ObjectToStringConverter());

		converterRegistry.addConverter(new NumberToCharacterConverter());
		converterRegistry.addConverterFactory(new CharacterToNumberFactory());

		converterRegistry.addConverter(new StringToBooleanConverter());
		converterRegistry.addConverter(Boolean.class, String.class, new ObjectToStringConverter());

		converterRegistry.addConverterFactory(new StringToEnumConverterFactory());
		converterRegistry.addConverter(new EnumToStringConverter((ConversionService) converterRegistry));

		converterRegistry.addConverterFactory(new IntegerToEnumConverterFactory());
		converterRegistry.addConverter(new EnumToIntegerConverter((ConversionService) converterRegistry));

		converterRegistry.addConverter(new StringToLocaleConverter());
		converterRegistry.addConverter(Locale.class, String.class, new ObjectToStringConverter());

		converterRegistry.addConverter(new StringToCharsetConverter());
		converterRegistry.addConverter(Charset.class, String.class, new ObjectToStringConverter());

		converterRegistry.addConverter(new StringToCurrencyConverter());
		converterRegistry.addConverter(Currency.class, String.class, new ObjectToStringConverter());

		converterRegistry.addConverter(new StringToPropertiesConverter());
		converterRegistry.addConverter(new PropertiesToStringConverter());

		converterRegistry.addConverter(new StringToUUIDConverter());
		converterRegistry.addConverter(UUID.class, String.class, new ObjectToStringConverter());
	}

}

        我们可以看得到,这个DefaultConversionService里面主要是注册了一些Converter和一些ConverterFactory。当需要集中整个类层次结构的转换逻辑时(例如,从转换String为Enum对象时),可以实现 ConverterFactory。需要复杂的Converter实现时,请考虑使该 GenericConverter接口。使用更灵活但不太强类型的签名Converter,GenericConverter支持在多个源类型和目标类型之间进行转换。此外,GenericConverter还可以在实现转换逻辑时使用可用的源和目标字段上下文。

        以上还是一些赋值的操作,真正进行实例化的还是在:preInstantiateSingletons,我們來看下他具体的源码:

	@Override
	public void preInstantiateSingletons() throws BeansException {
		if (logger.isTraceEnabled()) {
			logger.trace("Pre-instantiating singletons in " + this);
		}

		// 创建BeanDefinitionNames的副本BeanNames用于后续的遍历,以允许init等方法注册新的bean定义.
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// 遍历所有的beanNames,触发所有非懒加载单例bean的初始化,即:创建所有的单实例Bean
		for (String beanName : beanNames) {
			// 获取beanName对应的MergedBeanDefinition.在实例化之前将所有的beanDefiniton对象在转换成RootBeanDefinition,进行缓存,后续在需要马上实例化的时候直接获取定义信息,而定义信息中
			// 如果包含了父类就需要先实例化父类。
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			// 如果bd对应的Bean实例满足:(不是抽象类 && 是单例 && 不是懒加载)
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
 				// 判断BeanName对应的Bean实例是否是FactoryBean.
				/**
				 * BeanFactory 与FactoryBean的区别
				 * 相同点:都是用来创建bean对象的
				 * 不同点:
				 * 如果使用了BeanFactory那么就必须要严格遵循SpringBean的生命周期接口,例如从实例化 ——>初始化等等一系列方法,此流程非常的负责且麻烦
				 * 如果使用FactotyBean则创建bean就更加方便简单,不需要遵循spring的生命周期流程,
				 * 他主要有getObject():直接返回一个对象,isSingleton():判断是否是单例,getObjectTye():返回需要返回对象的类型三个方法。
				 */
				if (isFactoryBean(beanName)) {
					// 通过beanName获取FactoryBean的实例,factoryBean的名称是:"&" + beanName
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						final FactoryBean<?> factory = (FactoryBean<?>) bean;
						boolean isEagerInit;
						// 判断这个FactoryBean是否需要紧急初始化.
						// System.getSecurityManager()方法是获取系统权限管理器,Java为了防止恶意代码执行(修改,删除操作系统文件),做了权限管理,
						//   默认的安全管理器配置文件是: $JAVA_HOME/jre/lib/security/java.policy
						/**
						 * 在做访问控制决定时,如果遇到通过调用不带上下文参数(请参阅下文,以获取关于上下文参数的信息)的 doPrivileged 标记为“特权”的调用方,
						 *  则 checkPermission 方法将停止检查。如果该调用方的域具有指定的权限,则不进行进一步检查,并且 checkPermission 正常返回,
						 *  指示允许所请求的访问。如果该域不具有指定的权限,则通常抛出异常。
						 *
						 *
						 *  AccessController.doPrivileged()方法的例子:
						 *  假设有这样一种情况:A程序想在 C:\\Users\\Jack\\Desktop\\test1  这个目录中新建一个文件,但是它没有相应的权限,
						 *   但是它引用了另外一个Jar包B,刚好B有权限在C:\\Users\\Jack\\Desktop\\test1目录中新建文件,
						 *   还有更巧的是B在新建文件的时候采用的是AccessController.doPrivileged方法进行的,这种情况下,A就可以调用B的创建文件的方法进行创建文件了。
						 */
						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) {
							// 如果需要紧急初始化,则通过beanName获取Bean的实例.
							getBean(beanName);
						}
					}
				}
				else {
					// 如果BeanName对应的Bean实例不是FactoryBean,则通过BeanName去获取Bean实例.
					getBean(beanName);
				}
			}
		}

		/**
		 * 上一步for循环中已经创建完了所有的单实例Bean,这个for循环中,会拿出所有的单实例Bean,
		 *   然后遍历,判断单实例bean是否实现了SmartInitializingSingleton接口,如果实现了该接口,
		 *   则调用单实例Bean的afterSingletonsInstantiated方法
		 */
		for (String beanName : beanNames) {
			// 获取beanName对应的bean实例
			Object singletonInstance = getSingleton(beanName);
			// 判断当前的bean是否实现了SmartInitializingSingleton接口.
			if (singletonInstance instanceof SmartInitializingSingleton) {
				final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				// 触发SmartInitializingSingleton实现类的afterSingletonInstantiated方法.
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}, getAccessControlContext());
				}
				else {
					/**
					 * 如果实现了SmartInitializingSingleton接口,则会调用afterSingletonInstantiated方法
					 *   例如@EventListener注解的实现原理,就是利用EventListenerMethodProcessor后置处理器完成的,
					 *   而在EventListenerMethodProcessor中就是实现了SmartInitializingSingleton接口
					 */
					smartSingleton.afterSingletonsInstantiated();
				}
			}
		}
	}

       在之后的内容你可能会频繁的见到 “MergedBeanDefinition” 这个词,因此这边先稍微讲解一下,有助于你更好的理解。 MergedBeanDefinition:这个词其实不是一个官方词,但是很接近,该词主要是用来表示 “合并的 bean 定义”,因为每次都写 “合并的 bean 定义” 有点太绕口, 因此我在之后的注释或解析中或统一使用 MergedBeanDefinition 来表示 “合并的 bean 定义”。 之所以称之为 “合并的”,是因为存在 “子定义” 和 “父定义” 的情况。对于一个 bean 定义来说,可能存在以下几种情况: (1)该 BeanDefinition 存在 “父定义”:首先使用 “父定义” 的参数构建一个 RootBeanDefinition,然后再使用该 BeanDefinition 的参数来进行覆盖。 (2)该 BeanDefinition 不存在 “父定义”,并且该 BeanDefinition 的类型是 RootBeanDefinition:直接返回该 RootBeanDefinition 的一个克隆。 (3)该 BeanDefinition 不存在 “父定义”,但是该 BeanDefinition 的类型不是 RootBeanDefinition:使用该 BeanDefinition 的参数构建一个 RootBeanDefinition。 之所以区分出2和3,是因为通常 BeanDefinition 在之前加载到 BeanFactory 中的时候,通常是被封装成 GenericBeanDefinition 或 ScannedGenericBeanDefinition, 但是从这边之后 bean 的后续流程处理都是针对 RootBeanDefinition,因此在这边会统一将 BeanDefinition 转换成 RootBeanDefinition。 在我们日常使用的过程中,通常会是上面的第3种情况。如果我们使用 XML 配置来注册 bean,则该 bean 定义会被封装成:GenericBeanDefinition; 如果我们使用注解的方式来注册 bean,也就是  + @Compoment,则该 bean 定义会被封装成 ScannedGenericBeanDefinition。

	protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
		// Quick check on the concurrent map first, with minimal locking.
		// 检查beanName对应的MergedBeanDefinition是否存在于缓存中.
		RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
		if (mbd != null) {
			// 如果存在于缓存中,则直接返回.
			return mbd;
		}
		// 如果不再缓存中
		//  先调用getBeanDefinition()方法根据beanName获取对应的BeanDefinition,从beanDefinitionMap缓存中获取,获取不到直接抛异常.
		//  然后调用getMergedBeanDefinition(beanName, getBeanDefinition(beanName))方法根据beanName和对应的beanDefinition获取mergedBeanDefinition.
		return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
	}

	protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
			throws BeanDefinitionStoreException {

		return getMergedBeanDefinition(beanName, bd, null);
	}

protected RootBeanDefinition  getMergedBeanDefinition(
			String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
			throws BeanDefinitionStoreException {

		// 加同步锁,然后进行操作.
		synchronized (this.mergedBeanDefinitions) {
			// 用于存放返回结果.
			RootBeanDefinition mbd = null;

			// Check with full lock now in order to enforce the same merged instance.
			if (containingBd == null) {
				// 检查beanName对应的MergedBeanDefinition是否存在于缓存中.
				mbd = this.mergedBeanDefinitions.get(beanName);
			}
			// 如果beanName对应的BeanDefinition不在缓存中时
			if (mbd == null) {
				if (bd.getParentName() == null) {
					// 如果bd的parentName为空,表示bd没有父定义,不需要与父定义进行合并操作.即:bd的MergedBeanDefinition就是bd自己
					// Use copy of given root bean definition.
					if (bd instanceof RootBeanDefinition) {
						// 如果bd的类型为RootBeanDefinition,则bd的MergedBeanDefinition就是bd自己,直接克隆一个副本
						mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
					}
					else {
						// 否则使用bd构建一个RootBeanDefinition.
						// 一般情况下,BeanDefinition在被加载之后是GenericBeanDefinition(xml) 或者 ScannedGenericBeanDefinition(注解)
						mbd = new RootBeanDefinition(bd);
					}
				}
				else {
					// Child bean definition: needs to be merged with parent.
					// 否则,bd存在着父定义,需要和父定义合并.
					BeanDefinition pbd;
					try {
						// 获取父定义的BeanName.
						String parentBeanName = transformedBeanName(bd.getParentName());
						// 如果父定义的beanName和当前bean的beanName不同
						if (!beanName.equals(parentBeanName)) {
							// 则获取父定义的MergedBeanDefinition(也就是bd的爷爷定义...)

							/**
							 * 一般情况下,Spring 通过反射机制利用 bean 的  class 属性指定实现类来实例化 bean。
							 *   而 FactoryBean 是一种特殊的 bean,它是个工厂 bean,可以自己创建 bean 实例,如果一个类实现了 FactoryBean 接口,
							 *   则该类可以自己定义创建实例对象的方法,只需要实现它的 getObject() 方法。
							 *
							 * 很多中间件都利用 FactoryBean 来进行扩展。例如:
							 *
							 * public class AppleFactoryBean implements FactoryBean<Apple> {
									@Override
									public Apple getObject() throws Exception {
										Apple apple = new Apple();
										apple.setName("bigApple");
										return apple;
									}
									@Override
									public Class<?> getObjectType() {
										return Apple.class;
									}
									@Override
									public boolean isSingleton() {
										return true;
									}
								}
							 注意:
							 为了区分 “FactoryBean” 和 “FactoryBean 创建的 bean 实例”,Spring 使用了 “&” 前缀。假设我们的 beanName 为 apple,
							   则 getBean("apple") 获得的是 AppleFactoryBean 通过 getObject() 方法创建的 bean 实例;
							   而 getBean("&apple") 获得的是 AppleFactoryBean 本身。
							 *
							 */
							pbd = getMergedBeanDefinition(parentBeanName);
						}
						else {
							// 如果父定义的beanName和bd的beanName相同,则拿到父亲的BeanFactory
							// 只有存在父BeanFactory的情况下,才允许父定义beanName与自己相同,否则就是将自己设置为父定义.
							BeanFactory parent = getParentBeanFactory();
							// 如果父BeanFactory是ConfigurableBeanFactory,则通过BeanFactory获取父定义的MergedBeanDefinition.
							if (parent instanceof ConfigurableBeanFactory) {
								pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
							}
							else {
								// 否则抛出异常.
								throw new NoSuchBeanDefinitionException(parentBeanName,
										"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
										"': cannot be resolved without an AbstractBeanFactory parent");
							}
						}
					}
					catch (NoSuchBeanDefinitionException ex) {
						throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
								"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
					}
					// Deep copy with overridden values.
					// 使用父定义pbd构建一个新的RootBeanDefinition对象(通过深拷贝)
					mbd = new RootBeanDefinition(pbd);
					// 然后使用bd覆盖父定义.
					mbd.overrideFrom(bd);
				}

				// Set default singleton scope, if not configured before.
				// 如果没有设置Scope属性,默认设置为singleton.
				if (!StringUtils.hasLength(mbd.getScope())) {
					mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
				}

				// A bean contained in a non-singleton bean cannot be a singleton itself.
				// Let's correct this on the fly here, since this might be the result of
				// parent-child merging for the outer bean, in which case the original inner bean
				// definition will not have inherited the merged outer bean's singleton status.
				// 如果containingBd不为空 && 不是单实例的 && mbd为单实例,则将mbd的scope属性设置为containingBd的scope属性.
				if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
					mbd.setScope(containingBd.getScope());
				}

				// Cache the merged bean definition for the time being
				// (it might still get re-merged later on in order to pick up metadata changes)
				// 如果containingBd为空,而且设置了缓存Bean的元数据,则将beanName和mbd放入到beanDefinition的缓存中,便于以后可以直接取出使用.
				if (containingBd == null && isCacheBeanMetadata()) {
					this.mergedBeanDefinitions.put(beanName, mbd);
				}
			}
			return mbd;
		}
	}

        好了,这一节我们先讲到这里,这里大家应该而已晓得怎么自定义一个converter,跟了解getMergedLocalBeanDefinition做了哪些事情,大家可以看到,在实例化之前这里会先去判断是不是FactoryBean。       

        我们可以思考一个问题,FactoryBean跟BeanFactory有哪些区别,Spring是如何去管理FactoryBean的?

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值