栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring bean属性注入方式解析-上

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring bean属性注入方式解析-上

目录

一、Spring 注入属性的方式

1.1 通过名称注入(Autowire.BY_NAME,默认Autowire.NO)

 1.2 通过类型(Autowire.BY_TYPE)注入

 1.3 通过@Autowired注入


一、Spring 注入属性的方式

1.1 通过名称注入(Autowire.BY_NAME,默认Autowire.NO)
@Component
public class Apple {
}


@Configuration
public class ByNameAutowaire {
	//找对应Apple的set方法
	@Bean(autowire = Autowire.BY_NAME)
	public Fruit fruit(){
		return new Fruit();
	}
}


public class Fruit {
	private Apple apple;

	public Apple getApple() {
		return apple;
	}

	public void setApple(Apple apple) {
		this.apple = apple;
	}
}

 在Fruit中注入Apple属性,使用byName的方式,必须在Fruit中有对应的set()方法,在进行属性注入时,找的是set方法对应的bean的名字(比如setApple()方法找的就是apple这个bean对象)。在此时并没有进行属性的注入,而是将它放进了newPvs中,后续进行赋值。在找方法时需要如下的条件才满足(unsatisfiedNonSimpleProperties):

        1. 必须要有set方法

        2.   pvs中不存在

        3. 不是简单类型(CharSequence、Enum、Number、Date、Locale、URI、URL)

所以,以上几种类型使用@Bean(autowire = Autowire.BY_NAME)不会注入

	protected void autowireByName(
			String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
		//从我们的bean定义中解析出我们的所有属性对象
		String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
		//循环我们当前bean的属性
		for (String propertyName : propertyNames) {
			if (containsBean(propertyName)) {
				//显示的调用getBean所有属性的名称bean显示调用BeanFactory
				Object bean = getBean(propertyName);
				//把我们依赖的属性添加到pvs中
				pvs.add(propertyName, bean);
				//注册当前bean和属性依赖bean的依赖关系
				registerDependentBean(propertyName, beanName);
				if (logger.isDebugEnabled()) {
					logger.debug("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");
				}
			}
		}
	}

--------------------------unsatisfiedNonSimpleProperties-------------------


	protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
		Set result = new TreeSet<>();
        //这个可以再后置处理器中设置                    MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition
        //MutablePropertyValues pvs = new MutablePropertyValues();
        //pvs.add("apple", new Apple());
        //beanDefinition.setPropertyValues(pvs);
       
		PropertyValues pvs = mbd.getPropertyValues();
		PropertyDescriptor[] pds = bw.getPropertyDescriptors();
		for (PropertyDescriptor pd : pds) {
			//set方法不为空||pd.getName=set的名字,pvs中不存在 ||不是简单属性则加入数组
			if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&
					//isSimpleProperty属性排除
					!BeanUtils.isSimpleProperty(pd.getPropertyType())) {
				result.add(pd.getName());
			}
		}
		return StringUtils.toStringArray(result);
	}

 1.2 通过类型(Autowire.BY_TYPE)注入
@Configuration
public class ByTypeAutowaire {
	//找对应Apple的set方法
	@Bean(autowire = Autowire.BY_TYPE)
	public Fruit fruit(){
		return new Fruit();
	}
}

 原理和byName类似,byType则是去找参数对应的类型进行注入,放入对应的pvs中

 1.3 通过@Autowired注入
@Component
public class Fruit {
	private Apple apple;

	@Autowired
	public Apple getApple() {
		return apple;
	}

	public void setApple(Apple apple) {
		this.apple = apple;
	}
}

spring在创建bean时通过后置处理器AutowiredAnnotationBeanPostProcessor对@Autowired属性进行解析(AbstractAutowireCapableBeanFactory.populateBean)

AutowiredAnnotationBeanPostProcessor继承关系如下所示:MergedBeanDefinitionPostProcessor后置处理器在推断构造函数调用后,进行调用postProcessMergedBeanDefinition方法,先于赋值属性调用。

通过findAutowiringMetadata方法找到带有Autowired注解的属性,并将对应的属性放入injectionMetadataCache中,方便后续在执行属性赋值的时候可直接从缓存中进行获取

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);
					}
					//寻找对应方法加了@Autowired的
					metadata = buildAutowiringMetadata(clazz);
					this.injectionMetadataCache.put(cacheKey, metadata);
				}
			}
		}
		return metadata;
	}

 接下来看寻找@Autowired具体的方法(buildAutowiringMetadata)。遍历类的属性和方法看是否有@Value @Autowired @Inject注解如果有其中一个。并且不是static修饰的方法或者字段则构建AutowiredFieldElement、AutowiredMethodElement放入currElements集合中。

	private InjectionMetadata buildAutowiringMetadata(final Class clazz) {
		List elements = new ArrayList<>();
		Class targetClass = clazz;

		do {
			final List currElements = new ArrayList<>();
			//遍历字段
			ReflectionUtils.doWithLocalFields(targetClass, field -> {
				// @Value @Autowired @Inject注解
				AnnotationAttributes ann = findAutowiredAnnotation(field);
				if (ann != null) {
					//static不会给属性赋值
					if (Modifier.isStatic(field.getModifiers())) {
						if (logger.isWarnEnabled()) {
							logger.warn("Autowired annotation is not supported on static fields: " + field);
						}
						return;
					}
					boolean required = determineRequiredStatus(ann);
					currElements.add(new AutowiredFieldElement(field, required));
				}
			});

			//遍历方法
			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))) {
					if (Modifier.isStatic(method.getModifiers())) {
						if (logger.isWarnEnabled()) {
							logger.warn("Autowired annotation is not supported on static methods: " + method);
						}
						return;
					}
					if (method.getParameterCount() == 0) {
						if (logger.isWarnEnabled()) {
							logger.warn("Autowired annotation should only be used on methods with parameters: " +
									method);
						}
					}
					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);
	}

 在spring进行属性注入时,直接从缓存中取到之前解析的数据,分别对属性字段和方法进行注入即可。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1005889.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号