ByName进行依赖注入:
获取到set方法中的唯一参数的参数类型,并且根据该类型去容器中获取bean。
如果找到多个,会报错。
ByType简单介绍
- 本文源码基于spring-framework-5.3.10。
- 在创建Bean的时候会进行依赖注入
- 源码位置在:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByType(String, AbstractBeanDefinition, BeanWrapper, MutablePropertyValues)
ByType的原理
- 获取到set方法中的唯一参数的参数类型,并且根据该类型去容器中获取bean
- 如果找到多个,会报错。
ByType依赖注入的源码分析
protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
// 得到类型转化器,默认与BeanWrapper同一个
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
// 获取当前Bean中能进行自动注入的属性名
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类型:所有类都是Obj的子类导致选择太多,不知道注入那个Bean
if (Object.class != pd.getPropertyType()) {
// 得到当前set方法参数信息
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
// Do not allow eager init for type matching in case of a prioritized post-processor.
// eager表示立即初始化,表示在根据类型查找Bean时,允不允许进行Bean的创建,如果当前bean实现了PriorityOrdered,那么则不允许
// 为什么不允许,因为我自己是PriorityOrdered,是优先级最高的,不能有比我创建得更早的
boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
// 构建一个依赖描述器
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
// 根据类型找到的结果:比较复杂,在@Autowired中深入分析
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
// 得到的结果不是null,放入属性对应关系中
if (autowiredArgument != null) {
pvs.add(propertyName, autowiredArgument);
}
// 循环注入到当前bean所依赖的bean,autowiredBeanNames是当前bean锁依赖的bean集合
for (String autowiredBeanName : autowiredBeanNames) {
registerDependentBean(autowiredBeanName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
propertyName + "' to bean named '" + autowiredBeanName + "'");
}
}
autowiredBeanNames.clear();
}
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
}
}
}
获取当前Bean中能进行自动注入的属性名:unsatisfiedNonSimpleProperties源码分析
protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
// 定义能进行自动注入的熟悉名称集合
Set<String> result = new TreeSet<>();
// 获取当前BeanDefinition自己设置的属性
PropertyValues pvs = mbd.getPropertyValues();
// 得到当前的属性描述器
PropertyDescriptor[] pds = bw.getPropertyDescriptors();
// 什么样的属性能进行自动注入?
// 1.该属性有对应的set方法
// 2.没有在ignoredDependencyTypes中,如果该属性对应的set方法是实现了某个接口中所定义的,那么接口没有在ignoredDependencyInterfaces中
// 3.程序员自己没有给当前属性设置值
// 4.属性类型不是简单类型,比如int、Integer、int[]、Date、Number、URL.....
for (PropertyDescriptor pd : pds) {
if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&
!BeanUtils.isSimpleProperty(pd.getPropertyType())) {
result.add(pd.getName());
}
}
// 返回当前的名字集合
return StringUtils.toStringArray(result);
}
结束语
- 获取更多本文的前置知识文章,以及新的有价值的文章,让我们一起成为架构师!
- 关注公众号,可以让你对MySQL、并发编程、spring源码有深入的了解!
- 关注公众号,后续持续高效的学习JVM!
- 这个公众号,无广告!!!每日更新!!!