概述
填充属性
结合spring源码和 https://www.processon.com/view/link/5dec9a96e4b0c080dba0305b 上总结的流程图一起看,效果会更好。
书接上篇,继续分析populateBean(beanName, mbd, instanceWrapper);
这个方法。
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
...
//这儿,可以通过InstantiationAwareBeanPostProcessors.postProcessAfterInstantiation 方法,来自定义的填充bean的属性。spring的扩展点之一。
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
if (!continueWithPropertyPopulation) {
return;
}
//bean的属性和值的封装。
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
//如果在bean定义中配置了自动装配,则这里面会解析自动装配对应的bean。
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
//byName方式自动装配
// Add property values based on autowire by name if applicable.
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
//byType方式自动装配
// Add property values based on autowire by type if applicable.
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
//新的属性和值对象中会包含自动装配识别的bean。
pvs = newPvs;
}
//如果有 InstantiationAwareBeanPostProcessor,则会调用InstantiationAwareBeanPostProcessor.postProcessPropertyValues方法,这里面可以修改pvs,直接修改bean实例的属性等。@Autowired 注解的解析和属性注入触发点就在这儿。
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
//将pvs中的值注入到bean实例中去。
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
@Autowired 解析
我们来看下最常用的 @Autowired 注解是如何实现的。在AnnotationApplicationContext实例化的第一步,往容器中注册spring内部的组件时,会注册AutowiredAnnotationBeanPostProcessor,它实现了 InstantiationAwareBeanPostProcessor,因此在上一步的属性注入中,会触发AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues 方法调用:
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
//构建注入元信息
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
//注入
metadata.inject(bean, beanName, pvs);
}
...
return pvs;
}
简单的看下构建注入元信息方法
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
//先从缓存中拿,拿到了直接返回,没拿到就去解析构建,然后放到缓存中
// Fall back to class name as cache key, for backwards compatibility with custom callers.
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
//解析类信息,构建注入元信息。
metadata = buildAutowiringMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
具体构建过程:
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
//循环解析父类。
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
//doWithLocalFields简单的模板方法,这个代码块时对当前解析的类的所有字段解析,找到有注入相关注解(@Autowired @Value @Inject),包装为AutowiredFieldElement放到currElements中。
ReflectionUtils.doWithLocalFields(targetClass, field -> {
AnnotationAttributes ann = findAutowiredAnnotation(field);
if (ann != null) {
...
boolean required = determineRequiredStatus(ann);
currElements.add(new AutowiredFieldElement(field, required));
}
});
//doWithLocalMethods同理,这个代码块时对当前解析的类的所有方法解析,找到有注入相关注解(@Autowired @Value @Inject),包装为AutowiredMethodElement放到currElements中。
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
....
boolean required = determineRequiredStatus(ann);
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new AutowiredMethodElement(method, required, pd));
}
});
elements.addAll(0, currElements);
//递归解析父类
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return new InjectionMetadata(clazz, elements);
}
注入元信息构建完成之后,接下来就是注入了:
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection<InjectedElement> checkedElements = this.checkedElements;
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
...
//遍历没个需要注入的属性或者方法,进行注入
for (InjectedElement element : elementsToIterate) {
...
//具体注入
element.inject(target, beanName, pvs);
}
}
}
在构建注入元信息时,属性注入元信息构建的类型是AutowiredFieldElement,方法注入元信息构建的类型是AutowiredMethodElement,因此在具体注入时,会走不同的分支,已属性注入为例【方法注入的实现思路是一致的,只不过需要解析的是方法的参数值】:
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
//要注入的值已经解析过了,那么直接用缓存的值
if (this.cached) {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
else {
//没有缓存,那么需要将要注入的值解析出来,DependencyDescriptor是描述符,对依赖信息的封装。
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
Assert.state(beanFactory != null, "No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter();
try {
//调用beanFactory的解析依赖
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
...
//缓存处理,注意缓存技巧,能缓存最终结果就缓存最终结果,缓存不了就缓存中间结果。
synchronized (this) {
if (!this.cached) {
if (value != null || this.required) {
this.cachedFieldValue = desc;
//注册依赖(两个map)
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
this.cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
else {
this.cachedFieldValue = null;
}
this.cached = true;
}
}
}
//反射注入属性值
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
注入中最为关键的代码,beanFactory的resolveDependency方法:
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
//对注入是Optional类型的支持
if (Optional.class == descriptor.getDependencyType()) {
return createOptionalDependency(descriptor, requestingBeanName);
}
//对注入是ObjectFactory和ObjectProvider类型的支持
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
//对JSR330,javax.inject.Provider的支持
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
//真正的解析依赖,Optional类型,ObjectFactory和ObjectProvider类型 都是对这个的简单包装。
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
终于要真正解析了, 找到想要的bean,注意这里面会触发对依赖bean的getBean动作,形成递归调用getBean方法:
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
...
Class<?> type = descriptor.getDependencyType();
//扩展点,默认调用SimpleAutowireCandidateResolver.getSuggestedValue,返回null
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());
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
//对注入的是数组、集合、Map类型的处理。
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
//从容器中查找符合的beanDefinition。里面的逻辑大概为,先通过类型找到所有的bean,然后做一些特殊处理,比如是不是在spring的注入类型缓存中【spring框架本身没用,也算一个扩展点】,找到的beanDefinition支不支持自动注入【默认支持】等处理。
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
//如果没有找到,并且required为true,则抛错。
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName; //注入的beanName
Object instanceCandidate; //注入的bean实例
if (matchingBeans.size() > 1) {
//找到的beanDefinition多于一个时,先找有没有@Primary注解的,有就直接返回,再找@Priority,如果有多个,找优先级最高的那个返回;最后兜底,找候选bean中,有没有名称和注入的属性名是一样的,找到了就返回;如果都没有找到,返回null
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
//没有找到匹配的,并且required为true,则抛错。
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(type, matchingBeans);
}
else {
// In case of an optional Collection/Map, silently ignore a non-unique case:
// possibly it was meant to be an empty collection of multiple regular beans
// (before 4.3 in particular when we didn't even look for collection beans).
return null;
}
}
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else {
//只找到一个,好说,直接使用
// We have exactly one match.
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
if (instanceCandidate instanceof Class) {
//前面的解析得出的是要注入的beanName,这个方法就是通过beanName解析出bean来,默认就是调用getBean方法。
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
...
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
到这儿,基本上分析清楚了 @Autowired 是怎么完成属性的注入了(方法的注入几乎一样)。
单例bean循环依赖解决
现在,可以通过一个示例来分析下,spring是如何通过缓存暴露早期对象来解决循环依赖问题的。
说,有两个形成循环依赖的组件ComponentA和ComponentB:
@Component
@Data
public class ComponentA {
@Autowired
private ComponentB componentB;
}
@Component
@Data
public class ComponentB {
@Autowired
private ComponentA componentA;
}
跟上配置类和启动代码:
@Configuration
@ComponentScan
public class MainConfig {
}
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
context.registerShutdownHook();
}
}
在分析之前,先通过DefaultSingletonBeanRegistry.getSingleton方法来认识下创建单例bean用到的3个缓存:
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//this.singletonObjects 完整单例缓存【1级缓存】,缓存的是已经完全创建好的单例bean
Object singletonObject = this.singletonObjects.get(beanName);
//this.singletonsCurrentlyInCreation 保存当前正在创建的单例beanName,一个单例Bean只有正在创建的过程中,递归getBean自己时,才会形成循环依赖。这个属性主要用于优化
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
//this.earlySingletonObjects 早期单例bean缓存【2级缓存】,缓存刚实例化出来,但还没有填充属性和初始化的单例bean。这个也是用来加速优化用的。
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
//this.singletonFactories 早期单例工厂对象缓存【3级缓存】,缓存获取早期单例bean的对象工厂实例。
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//调用3级缓存中的对象工厂的getObject()方法,得到单例bean的早期实例,反手加入到二级缓存中,并将3级缓存清除。这样请求多次的时候就不用重复调用getObject方法。
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
假如在实例化单例bean时,先实例化ComponentA,即getBean(“componentA”)做为入口进行分析,
建议看图【单例bean的循环依赖示例】:https://www.processon.com/view/link/5dec9a96e4b0c080dba0305b
那么核心的调用链:
getBean(“componentA”) -> doGetBean(“componentA”) -> getSingleton(“componentA”)【第一次调用,返回null】-> getSingleton(“componentA”, ()->createBean()) 【回调createBean的前后做一些处理,前置处理 将"componentA"加入singletonsCurrentlyInCreation中, 后置处理从singletonsCurrentlyInCreation删除"componentA",并加入完整单例缓存】
-> createBean(“componentA”) -> doCreateBean(“componentA”) -> createBeanInstance(“componentA”)【实例化"componentA",新鲜出炉,早期对象】 -> addSingletonFactory(“componentA”,早期对象包装的对象工厂) 【将早期对象"componentA"暴露到singletonFactories三级缓存中】
-> populateBean(“componentA”) -> postProcessPropertyValues(“componentA”) -> findAutowiringMetadata(“componentA”) -> resolveDependency(“componentA”) -> doResolveDependency(“componentA”)【解析到"componentA"的属性自动注入"componentB"】-> resolveCandidate(“componentB”)
-> getBean(“componentB”) -> …实例化"componentB",暴露"componentB"的早期对象到三级缓存,填充componentB属性时解析到依赖componentA,触发getBean(“componentA”)
-> getSingleton(“componentA”)【第二次调用,返回"componentA"早期对象】-> 完成componentB的属性填充,初始化componentB,加入到单例缓存中,返回componentB的完整实例 -> 完成componentA的属性填充,初始化componentA,加入到单例缓存中,返回componentA的完整实例。
autowireMode 解析
指定为byName时:
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
//获取beanDefinition中,非简单的属性名,这些属性就是需要去进行自动注入的要处理的
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
if (containsBean(propertyName)) {
//直接根据属性名字,到容器中去getBean。
Object bean = getBean(propertyName);
//加入到pvs,在后面统一绑定到属性上。
pvs.add(propertyName, bean);
//注册依赖关系(两个依赖关系的map)
registerDependentBean(propertyName, beanName);
...
}
....
}
}
指定为byType时:
protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
//遍历所有非简单属性
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
try {
//构建属性描述
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
// Don't try autowiring by type for type Object: never makes sense,
// even if it technically is a unsatisfied, non-simple property.
//属性的类型为Object时,byType不会理它。
if (Object.class != pd.getPropertyType()) {
//获取写方法参数,也就会setter方法的参数。
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
// Do not allow eager init for type matching in case of a prioritized post-processor.
boolean eager = !PriorityOrdered.class.isInstance(bw.getWrappedInstance());
//构建依赖描述
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
//使用容器的resolveDependency方法进行依赖解析,这儿就和前面解析@AutoWired用到的方法一样。
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
/加入到pvs,在后面统一绑定到属性上。
if (autowiredArgument != null) {
pvs.add(propertyName, autowiredArgument);
}
//注册依赖关系
for (String autowiredBeanName : autowiredBeanNames) {
registerDependentBean(autowiredBeanName, beanName);
....
}
autowiredBeanNames.clear();
}
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
}
}
}
本文主要分析了常规工作中,使用@Autowired注解时,spring是如何自动注入对应的依赖的,然后通过一个实际示例分析了spring是如果通过缓存早期对象的方式来解决单例bean的循环依赖问题的。
最后,请思考一个问题,单例bean的循环依赖问题中,如果是构造器注入的话,spring的这种方式能不能解决?为什么?在创建bean的过程中,有一步会校验多例bean的循环依赖,如果存在直接报错,spring又为什么不能解决多例bean的循环依赖问题?
最后
以上就是冷酷水池为你收集整理的Spring框架IOC容器初始化核心源码解析之五:单例Bean循环依赖解决和自动注入机制的全部内容,希望文章能够帮你解决Spring框架IOC容器初始化核心源码解析之五:单例Bean循环依赖解决和自动注入机制所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复