【spring】依赖注入之ByName方式注入

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!
  • 这个公众号,无广告!!!每日更新!!!
    作者公众号.jpg
posted @ 2022-02-22 23:44  程序java圈  阅读(178)  评论(0编辑  收藏  举报