ByName进行依赖注入:
如果方法名字以“get”开头,比如“getXXX”,那么name=XXX。
如果方法名字以“is”开头,比如“isXXX”,那么name=XXX。
如果方法名字以“set”开头,比如“setXXX”,那么name=XXX。
ByName简单介绍
- 本文源码基于spring-framework-5.3.10。
- 在创建Bean的时候会进行依赖注入
- 源码位置在:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByName(String, AbstractBeanDefinition, BeanWrapper, MutablePropertyValues)
ByName注册原理
- name:这个name并不是方法的名字,而是拿方法名字经过处理后的名字
- 如果方法名字以“get”开头,比如“getXXX”,那么name=XXX
- 如果方法名字以“is”开头,比如“isXXX”,那么name=XXX
- 如果方法名字以“set”开头,比如“setXXX”,那么name=XXX
ByName依赖注入的源码分析
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
// 当前Bean中能进行自动注入的属性名。简单说就是找有哪些set方法
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
// 遍历每个属性名,并去获取Bean对象,并设置到pvs中
for (String propertyName : propertyNames) {
// 当前Bean在spring容器中存在,可以进行获取
if (containsBean(propertyName)) {
// 获取Bean
Object bean = getBean(propertyName);
// 属性对应。@Autowired在这里会直接赋值
pvs.add(propertyName, bean);
// 记录一下propertyName对应的Bean被beanName给依赖了
registerDependentBean(propertyName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("Added autowiring by name from bean name '" + beanName +
"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
"' by name: no matching bean found");
}
}
}
}
获取当前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);
}
什么是属性描述器:getPropertyValues()源码分析
/*
* 当前类是属于java.beans下的。
* 表示javaBean的规范:属性私有化,有get、set方法
* 这里只列出来主要的属性
*/
public class PropertyDescriptor extends FeatureDescriptor {
// 属性名字
private String baseName;
// set方法名字。
private String writeMethodName;
// get方法名字
private String readMethodName;
// 如果方法名字以“get”开头,比如“getXXX”,那么name=XXX。如果方法名字以“is”开头,比如“isXXX”,那么name=XXX。如果方法名字以“set”开头,比如“setXXX”,那么name=XXX
private String name;
}
结束语
- 获取更多本文的前置知识文章,以及新的有价值的文章,让我们一起成为架构师!
- 关注公众号,可以让你对MySQL、并发编程、spring源码有深入的了解!
- 关注公众号,后续持续高效的学习JVM!
- 这个公众号,无广告!!!每日更新!!!
