我们都知道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. ListbeanNames = 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 SetautowiredBeanNames, @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
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实例化过程。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)