- 知识笔记-Spring装配Map、List原理
- 1、原因及问题
- 2、项目搭建
- 3、源码探寻
- 4、总结
原因:
在使用策略模式时,会创建一个工厂类,以选择具体使用哪个类来进行业务处理。
问题:
使用构造器进行属性注入时,Map可以注入值,HashMap却无法注入。
使用构造器进行属性注入时,List可以注入值,ArrayList却无法注入。
2、项目搭建项目地址:https://gitee.com/NIRLIN/Labs/tree/master/Lab-01
工厂类为水果类型,水果有多种种类,多种吃法
西瓜–切开吃
苹果–削皮、不削皮
项目创建使用:spring提供创建方法
org.springframework.boot spring-boot-starter-parent 2.6.7 org.springframework.boot spring-boot-starter org.projectlombok lombok true
工厂类:
@Slf4j
@Component
public class FruitFactory {
public FruitFactory(Map map, HashMap hashMap, List list, ArrayList arrayList) {
log.info("map-->{}", map);
log.info("hashMap-->{}", hashMap);
log.info("list-->{}", list);
log.info("arrayList-->{}", arrayList);
}
}
水果接口:
public interface FruitService {
void eatFruit();
}
苹果实现:
@Slf4j
@Service
public class AppleServiceImpl implements FruitService {
@Override
public void eatFruit() {
log.info("削皮或不削皮-->吃");
}
}
西瓜实现:
@Slf4j
@Service
public class WatermelonServiceImpl implements FruitService {
@Override
public void eatFruit() {
log.info("切开-->吃");
}
}
3、源码探寻
由此可看出map与list装配成功,但其实现类装配失败。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YQfQ8tGk-1652422087045)(知识笔记-Spring装配Map、List原理.assets/image-20220513131118094.png)]
往堆栈上方寻找,由此可看出:
装配由ConstructorResolver.autowireConstructor(String beanName, RootBeanDefinition mbd,
@Nullable Constructor>[] chosenCtors, @Nullable Object[] explicitArgs)完成。beanName=“fruitFactory”,装填参数仅部分存在值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YjG7NyjJ-1652422087048)(知识笔记-Spring装配Map、List原理.assets/image-20220513131420659.png)]
在ConstructorResolver.autowireConstructor中加入断点,判断值"fruitFactory".equals(beanName)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yeSLGUYa-1652422087052)(知识笔记-Spring装配Map、List原理.assets/image-20220513132045435.png)]
进行装配的值args,来自argsHolder.arguments。argsHolder.arguments来自,本类的createArgumentArray(
String beanName, RootBeanDefinition mbd, @Nullable ConstructorArgumentValues resolvedValues,
BeanWrapper bw, Class>[] paramTypes, @Nullable String[] paramNames, Executable executable,
boolean autowiring, boolean fallback)方法。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6Aq1CvT5-1652422087054)(知识笔记-Spring装配Map、List原理.assets/image-20220513132703691.png)]
在ConstructorResolver.createArgumentArray方法中resolveAutowiredArgument(MethodParameter param, String beanName,
@Nullable Set autowiredBeanNames, TypeConverter typeConverter, boolean fallback)对需要注入的参数进行注入
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dYbOD1mH-1652422087055)(知识笔记-Spring装配Map、List原理.assets/image-20220513133137337.png)]
经由beanFactory.resolveDependency注入,使用DefaultListableBeanFactory进行实现
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KaZ3DsoM-1652422087058)(知识笔记-Spring装配Map、List原理.assets/image-20220513133354047.png)]
通过doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter)进入
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-upAyqGsf-1652422087060)(知识笔记-Spring装配Map、List原理.assets/image-20220513133725008.png)]
由resolveMultipleBeans进行属性填充
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EbL8U16z-1652422087061)(知识笔记-Spring装配Map、List原理.assets/image-20220513134032593.png)]
核心:
org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveMultipleBeans
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h61xPnsw-1652422087062)(知识笔记-Spring装配Map、List原理.assets/image-20220513134413490.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HtQww1kB-1652422087062)(知识笔记-Spring装配Map、List原理.assets/image-20220513134221966.png)]
由源码可看出,对于map类型,只对Map接口进行属性赋值,对其实现类不会进行赋值,对于list也是同理
Mapresult = CollectionUtils.newLinkedHashMap(candidateNames.length);
对于map,spring装配时默认使用LinkedHashMap
4、总结以上为大致内容,水平有限,敬请谅解,项目已上传至gitee。https://gitee.com/NIRLIN/Labs



