FactoryBean它是怎么创建一个bean的?

FactoryBean它是怎么创建一个bean的?,第1张

FactoryBean它是怎么创建一个bean的? FactoryBean

我们都知道spring是通过ioc方式创建bean实例和初始化的,可以通过注解方式创建,如@Component、@Service、@Controller等等

也可以在@Configuration类中使用@Bean注解来创建
还有一种是通过FactoryBean接口来创建。


就是说如果初始化bean过程比较复杂,您可以创建自己的 FactoryBean,在该类中编写复杂的初始化逻辑,通过FactoryBean方式来创建。

The FactoryBean interface provides three methods:

T getObject()

boolean isSingleton()

Class getObjectType()

主要关注是getObject方法

FactoryBean创建bean过程分析

自定义一个FactoryBean类,创建MyInstance实例。

package com.example.demo.factorybean;

import org.springframework.beans.factory.FactoryBean;
import org.springframework.stereotype.Component;


@Component
public class MyFactoryBean implements FactoryBean {

    @Override
    public MyInstance getObject() throws Exception {
        // TODO: 2021-11-26  复杂逻辑
        return new MyInstance();
    }

    @Override
    public Class getObjectType() {
        return MyInstance.class;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}

启动spring boot应用后,查看org.springframework.beans.factory.support.DefaultListableBeanFactory#beanDefinitionMap

这里说下beanDefinitionMap这个Map,非常重要,要实例化的bean,必须在它里边,很厉害吧。它里面存储了所有bean和bean的信息(BeanDefinition)的关系,它的初始化过程参考:org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions

其中key是beanName,value是bean的定义信息(即BeanDefinition)

好,进入
org.springframework.context.support.AbstractApplicationContext#refresh方法,这个方法大家都很熟悉,spring启动后最终都会进入到这个方法。
再进入finishBeanFactoryInitialization方法,
查看beanFactory.preInstantiateSingletons()方法

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

		// Iterate over a copy to allow for init methods which in turn register new bean definitions.
		// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
		List beanNames = new ArrayList<>(this.beanDefinitionNames);

		// Trigger initialization of all non-lazy singleton beans...
		for (String beanName : beanNames) {
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				if (isFactoryBean(beanName)) {
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						final FactoryBean factory = (FactoryBean) bean;
						boolean isEagerInit;
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged((PrivilegedAction)
											((SmartFactoryBean) factory)::isEagerInit,
									getAccessControlContext());
						}
						else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean) factory).isEagerInit());
						}
						if (isEagerInit) {
							getBean(beanName);
						}
					}
				}
				else {
					getBean(beanName);
				}
			}
		}
	}

当创建MyFactoryBean时候,isFactoryBean(beanName)这个就是true,
会执行以下这句
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
对beanName前缀增加&符号,即beanName=’&myFactoryBean’,这里为什么加这个前置下面会说。

接着就是进入创建bean的核心逻辑,
doGetBean->createBean->doCreateBean

实例化bean是通过以下这个方法完成
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
此方法创建出来sharedInstance就是MyFactoryBean的实例,但是还没有初始化的。

接着
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
看以下部分

if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							// Explicitly remove instance from singleton cache: It might have been put there
							// eagerly by the creation process, to allow for circular reference resolution.
							// Also remove any beans that received a temporary reference to the bean.
							destroySingleton(beanName);
							throw ex;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

方法getObjectForBeanInstance,为什么创建bean了不直接返回而是进到这方法呢,这里就是给FactoryBean服务的。

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

		// Don't let calling code try to dereference the factory if the bean isn't a factory.
		if (BeanFactoryUtils.isFactoryDereference(name)) {
			if (beanInstance instanceof NullBean) {
				return beanInstance;
			}
			if (!(beanInstance instanceof FactoryBean)) {
				throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
			}
		}
		if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
			return beanInstance;
		}

		Object object = null;
		if (mbd == null) {
			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());
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}

if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
意思是:如果当前创建出来的bean不是一个FactoryBean或者是以字符串’&'开头的,那么直接返回即可,这里返回的就是MyFactoryBean这个我自定义的类。

否则会继续往下走,最终会调用FactoryBean的getObject方法,去创建真正的bean。

所以,这也是为什么上面调用getBean(name)之前要加一个’&'前缀了,这是因为对于spring来说,FactoryBean也是一个Bean,也应该管理起来,注入到spring容器中。

好,FactoryBean创建好了,也放到spring的一级缓存singletonObjects中了,那么如果我想要MyInstance这个对象呢?

比如我有个Service:

public class DemoService1 implements InitializingBean {

    @Autowired
    private MyInstance myinstance;

    DemoService1() {
    }
    
    @Override
    public void afterPropertiesSet() throws Exception {
        instance.todo();
    }
}

这个Service需要注入MyInstance这个对象。
这就涉及到doCreateBean中填充Bean属性的部分逻辑了,也就是populateBean方法,
可以参考:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean

这个方法就是完成属性的依赖注入的,主要是通过
AutowiredAnnotationBeanPostProcessor
CommonAnnotationBeanPostProcessor
这两个类来完成。

接着populateBean方法中
这段代码:

for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
					if (pvsToUse == null) {
						if (filteredPds == null) {
							filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
						}
						pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
						if (pvsToUse == null) {
							return;
						}
					}
					pvs = pvsToUse;
				}
			}

看到 PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName)
如果spring版本低可能会调用
ibp.postProcessPropertyValues这个,我这里展示的是5.1.6版本的,它们最终都会执行到类AutowiredAnnotationBeanPostProcessor中以下部分(前提是使用@Autowired注解来注入)

@Override
	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
		Injectionmetadata metadata = findAutowiringmetadata(beanName, bean.getClass(), pvs);
		try {
			metadata.inject(bean, beanName, pvs);
		}
		catch (BeanCreationException ex) {
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
		}
		return pvs;
	}

Injectionmetadata中存储的就是依赖的属性信息。

最终会走到
org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency以下部分:

public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
			@Nullable Set autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

		InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
		try {
			Object shortcut = descriptor.resolveShortcut(this);
			if (shortcut != null) {
				return shortcut;
			}

			Class type = descriptor.getDependencyType();
			Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
			if (value != null) {
				if (value instanceof String) {
					String strVal = resolveEmbeddedValue((String) value);
					BeanDefinition bd = (beanName != null && containsBean(beanName) ?
							getMergedBeanDefinition(beanName) : null);
					value = evaluateBeanDefinitionString(strVal, bd);
				}
				TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
				try {
					return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
				}
				catch (UnsupportedOperationException ex) {
					return (descriptor.getField() != null ?
							converter.convertIfNecessary(value, type, descriptor.getField()) :
							converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
				}
			}

			Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
			if (multipleBeans != null) {
				return multipleBeans;
			}

			Map matchingBeans = findAutowireCandidates(beanName, type, descriptor);
			if (matchingBeans.isEmpty()) {
				if (isRequired(descriptor)) {
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				return null;
			}

			String autowiredBeanName;
			Object instanceCandidate;

			if (matchingBeans.size() > 1) {
				autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
				if (autowiredBeanName == null) {
					if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
						return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
					}
					else {
						return null;
					}
				}
				instanceCandidate = matchingBeans.get(autowiredBeanName);
			}
			else {
				Map.Entry entry = matchingBeans.entrySet().iterator().next();
				autowiredBeanName = entry.getKey();
				instanceCandidate = entry.getValue();
			}

			if (autowiredBeanNames != null) {
				autowiredBeanNames.add(autowiredBeanName);
			}
			if (instanceCandidate instanceof Class) {
				instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
			}
			Object result = instanceCandidate;
			if (result instanceof NullBean) {
				if (isRequired(descriptor)) {
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				result = null;
			}
			if (!ClassUtils.isAssignablevalue(type, result)) {
				throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
			}
			return result;
		}
		finally {
			ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
		}
	}

Map matchingBeans = findAutowireCandidates(beanName, type, descriptor);
beanName就是依赖属性,即myinstance

那么这个matchingBeans最终会拿到的是MyFactoryBean这个类,接着
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
最终还是调用到了熟悉的:

public Object resolveCandidate(String beanName, Class requiredType, BeanFactory beanFactory)
			throws BeansException {

		return beanFactory.getBean(beanName);
	}

好,又回到了创建bean的过程,依然是跟创建MyFactoryBean一样,不过这时候的beanName是myInstance,它是没有带前缀’&'的,所以

if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {	destroySingleton(beanName);
							throw ex;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
这个判断就不会成立,因为beanInstance还是MyFactoryBean,但是name是myInstance,是没有带‘&’前缀的,所以会往下走,直到FactoryBean的getObject()方法,最终创建好,通过反射方式写入Service的属性。

这里说明下,beanInstance这次是从一级缓存singletonObjects中拿到的,因为第一次已经创建过一遍了,并且它是单例的,所以已经缓存起来了。

好了,以上就是FactoryBean创建bean实例化过程。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5606174.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-15
下一篇 2022-12-15

发表评论

登录后才能评论

评论列表(0条)

保存