Spring之寻找注入点详解
Spring在属性填充过程中,需要判断属性和方法是否为一个注入点,然后根据注入点找到对象赋值或者创建Bean进行赋值。
1、最外层属性赋值
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {// 寻找注入点InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);try {// 根据找到的注入点,属性注入metadata.inject(bean, beanName, pvs);}catch (BeanCreationException ex) {throw ex;}catch (Throwable ex) {throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);}return pvs;}
2、区分方法和属性,分开注入
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {Collection<InjectedElement> checkedElements = this.checkedElements;Collection<InjectedElement> elementsToIterate =(checkedElements != null ? checkedElements : this.injectedElements);if (!elementsToIterate.isEmpty()) {// 根据字段或方法进行注入for (InjectedElement element : elementsToIterate) {element.inject(target, beanName, pvs);}}}
3、字段注入的方式
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {Field field = (Field) this.member;Object value;if (this.cached) {try {value = resolvedCachedArgument(beanName, this.cachedFieldValue);}catch (NoSuchBeanDefinitionException ex) {// Unexpected removal of target bean for cached argument -> re-resolvevalue = resolveFieldValue(field, bean, beanName);}}else {value = resolveFieldValue(field, bean, beanName);}if (value != null) {ReflectionUtils.makeAccessible(field);field.set(bean, value);}}
- org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#resolveFieldValue
- 如果属性是一个懒加载的对象,会返回一个代理对象。
- 尝试从单例池中获取,如果存在则直接返回。
- 判断属性上是否含有@Vlaue注解(org.springframework.beans.factory.support.AutowireCandidateResolver#getSuggestedValue)
- 根据类型查找获选的BeanName(org.springframework.beans.factory.BeanFactoryUtils#beanNamesForTypeIncludingAncestors(org.springframework.beans.factory.ListableBeanFactory, java.lang.Class<?>, boolean, boolean))。
- 检查BeanDefinfition的autowieCandiateResolver(属性org.springframework.beans.factory.support.SimpleAutowireCandidateResolver#isAutowireCandidate)。
- 检查BeanDefinition的beanClass属性和当前的注入点type是否匹配。(org.springframework.beans.factory.support.GenericTypeAwareAutowireCandidateResolver#checkGenericTypeMatch。)
- 检查是否有@Qualifier注解(org.springframework.beans.factory.support.AutowireCandidateResolver#hasQualifier)
- 推断是否含有@Primary注解(org.springframework.beans.factory.support.DefaultListableBeanFactory#determinePrimaryCandidate)
4、方法注入的方法
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {if (checkPropertySkipping(pvs)) {return;}Method method = (Method) this.member;Object[] arguments;if (this.cached) {try {arguments = resolveCachedArguments(beanName);}catch (NoSuchBeanDefinitionException ex) {// Unexpected removal of target bean for cached argument -> re-resolvearguments = resolveMethodArguments(method, bean, beanName);}}else {arguments = resolveMethodArguments(method, bean, beanName);}if (arguments != null) {try {ReflectionUtils.makeAccessible(method);method.invoke(bean, arguments);}catch (InvocationTargetException ex) {throw ex.getTargetException();}}}
大致和属性方式注入相同,就不做具体描述。