AutowiredAnnotationBeanPostProcessor依赖注入解析

Spring的bean创建流程

当我们对spring深入了解后,我们会发现spring对bean的创建和管理的流程是很清晰的明了的,通过这篇文章Spring加载applicationContext.xml,我们可以很清楚的知道其实spring创建bean的流程是这样的:

首先,spring会先准备哪些bean是交由它创建的,这就是Spring加载applicationContext.xml这篇文章里面讲到的,加载applicationContext配置文件其实就是为了后续创建bean而做的准备阶段,怎么让spring知道自己要加载和创建哪些bean呢?这是通过spring提供的各个注解来实现,通过Service、Component、Controller等注解,spring可以扫描这些bean,并为他们准备了后续要创建bean所需要的信息,在spring里叫做definition

其次,当准备阶段做完后,Spring就会开启创建bean的过程,就是遍历所有的需要初始化的BeanDefinition,然后实例化这些bean,但是实例化的bean,实际上里面的属性和方法等对象是未实例化的,所以当创建了bean之后我们就需要去为这些目标bean里面注入他所需要的对象,这就是我们今天要讲的重点,spring的依赖注入。

最后一个流程就是遍历每个目标bean里面被注解Autowired、Value等注解标识的属性以及方法,然后实例化这些元素,然后注入。

控制反转和依赖注入

在我看来,控制反转和依赖注入是同一种概念,两种的唯一区别就是,控制反转是在理论层面上提出来的,而依赖注入更偏向于实现层面上的,简单来说,依赖注入是控制反转的一种实现形式,并无差别。在Spring中bean的创建就是通过依赖注入的形式实现控制反转的。

Spring的依赖注入的整个流程,首先Spring会遍历所有需要创建并实例化的bean,先实例化bean接下来就是为实例化好的bean,这时候我们称该bean为目标,为目标bean注入相应的对象,这些对象可以通过属性注入和方法注入两种方式来实现。

其次,Spring会找到目标bean里面的所有被Autowired、Value注解的属性和方法,然后执行创建实例化bean操作并返回值;

最后,通过返回的值反射注入到对应的对象,整个流程就结束了。整个流程如下:

Created with Raphaël 2.2.0 初始化 查找需要注入的属性和方法 为这些属性和方法创建并实例化 反射依赖注入bean 结束

AutowiredAnnotationBeanPostProcessor简介

AutowiredAnnotationBeanPostProcessor是BeanPostProcessor的实现类,能够自动装配被注解Autowired、Value注解的属性、setter方法以及配置方法,这些类成员能够被自动的检测到并注入。当然,AutowiredAnnotationBeanPostProcessor还支持JSR-330的Inject注解。简单来讲,AutowiredAnnotationBeanPostProcessor就是个依赖注入的处理器。

AutowiredAnnotationBeanPostProcessor只提供一个构造方法,该构造法设置了AutowiredAnnotationBeanPostProcessor处理器能够支持哪些注解,默认情况下支持3种Autowired、Value以及Inject,构造方法如下:

public AutowiredAnnotationBeanPostProcessor() {
		this.autowiredAnnotationTypes.add(Autowired.class);
		this.autowiredAnnotationTypes.add(Value.class);
		try {
			this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
					ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
			logger.info("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
		}
		catch (ClassNotFoundException ex) {
			// JSR-330 API not available - simply skip.
		}
	}

当然,AutowiredAnnotationBeanPostProcessor也支持自定义注解的发现,AutowiredAnnotationBeanPostProcessor类提供了两个方法来进行修改,如下:

public void setAutowiredAnnotationType(Class<? extends Annotation> autowiredAnnotationType) {
		Assert.notNull(autowiredAnnotationType, "'autowiredAnnotationType' must not be null");
		this.autowiredAnnotationTypes.clear();
		this.autowiredAnnotationTypes.add(autowiredAnnotationType);
	}

	
	public void setAutowiredAnnotationTypes(Set<Class<? extends Annotation>> autowiredAnnotationTypes) {
		Assert.notEmpty(autowiredAnnotationTypes, "'autowiredAnnotationTypes' must not be empty");
		this.autowiredAnnotationTypes.clear();
		this.autowiredAnnotationTypes.addAll(autowiredAnnotationTypes);
	}

所以,我们还能自定义Spring没有的注解,让AutowiredAnnotationBeanPostProcessor处理器也能自动的装配我们自定义的注解成员变量。

AutowiredAnnotationBeanPostProcessor依赖注入的入口函数

依赖注入是在什么时候执行的?答案是很明显的,依赖注入的时机是在bean被创建之后,就会马上执行依赖注入,所以AutowiredAnnotationBeanPostProcessor是在创建bean之后被调用,而调用的入口就是AutowiredAnnotationBeanPostProcessor的一个函数,函数如下:

public PropertyValues postProcessPropertyValues(
			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {

		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;
	}

当bean创建完后就会触发该方法来执行bean里面的属性和方法的注入流程,不过postProcessPropertyValues这个方法在后续高版本的Spring被替换掉了,但是具体的的注入流程没变化,不影响我们讲解依赖注入,让我们继续解析依赖注入的过程。参数bean其实就是创建好的要为其注入属性的目标bean,所以注入是在bean创建完后才执行的。其实在该方法被调用之前,还有一个方法会先被调用,这个方法就是postProcessMergedBeanDefinition,该方法的作用其实比较简单,就是为了缓存下后续需要用到数据,其实他的代码和上面的代码很像,如下:

@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		if (beanType != null) {
			InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
			metadata.checkConfigMembers(beanDefinition);
		}
	}

是不是很像,都调用了findAutowiringMetadata方法,而findAutowiringMetadata这个方法是有缓存的处理的,所以重复调用的话是直接从缓存获取数据,加快注入的效率。

查找目标类的注入属性及方法

接下来我们继续讨论findAutowiringMetadata这个方法,这个方法其实就是去查找被Autowired、@Value注解的所有属性和方法,当然包括了目标类的所有父类都会去查找,所以查找的过程其实是个递归的过程。找到所有的成员后,会执行注入元数据对象的创建即实例化InjectionMetadata对象并返回。我们来看下它的代码:

private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, 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);
					}
					try {
						metadata = buildAutowiringMetadata(clazz);
						this.injectionMetadataCache.put(cacheKey, metadata);
					}
					catch (NoClassDefFoundError err) {
						throw new IllegalStateException("Failed to introspect bean class [" + clazz.getName() +
								"] for autowiring metadata: could not find class that it depends on", err);
					}
				}
			}
		}
		return metadata;
	}

从源代码可以看出,查找的过程经过了缓存的处理,依赖注入的元数据创建完后都会put进去injectionMetadataCache这个map里面管理,下次进来的key如果是一样的话并存在于map里面就不会执行创建而是直接取缓存里面获取。那Spring到底是怎么样创建InjectionMetadata对象的,还有InjectionMetadata里面有什么内容,让我们继续来揭晓,首先我们看下InjectionMetadata这个类具体如下:
InjectionMetadata的结构图
这里面我们关注几个属性:

  1. injectedElements属性;

    所有的注入对象,包括属性、setter方法以及配置方法都会被扫描到并保存到这个集合中。InjectedElement有两种实现分别是:AutowiredFieldElement和AutowiredMethodElement,从名字可以看出一种是对field的包装一种是对method的包装。

  2. inject(Object target, String beanName, PropertyValues pvs)方法;

    遍历上面的injectedElements集合调用元素的注入方法其实是调用各自的具体的实现类的inject方法执行注入操作,代码如下:

    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) {
    				if (logger.isTraceEnabled()) {
    					logger.trace("Processing injected element of bean '" + beanName + "': " + element);
    				}
    				element.inject(target, beanName, pvs);
    			}
    		}
    	}
    

所以,buildAutowiringMetadata这个方法其实是完成了metadata的创建工作。

实例化需要注入的对象

我们以InjectedElement的一个实现类来解析依赖注入的操作,这个类就是上面提到的AutowiredFieldElement,这个类主要是非方法的属性的注入操作,我们直接看它重载了inject方法如下:

protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
			Field field = (Field) this.member;
			Object value;
			if (this.cached) {
				value = resolvedCachedArgument(beanName, this.cachedFieldValue);
			}
			else {
				DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
				desc.setContainingClass(bean.getClass());
				Set<String> autowiredBeanNames = new LinkedHashSet<String>(1);
				TypeConverter typeConverter = beanFactory.getTypeConverter();
				try {
					value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
				}
				catch (BeansException ex) {
					throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
				}
				synchronized (this) {
					if (!this.cached) {
						if (value != null || this.required) {
							this.cachedFieldValue = desc;
							registerDependentBeans(beanName, autowiredBeanNames);
							if (autowiredBeanNames.size() == 1) {
								String autowiredBeanName = autowiredBeanNames.iterator().next();
								if (beanFactory.containsBean(autowiredBeanName)) {
									if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
										this.cachedFieldValue = new ShortcutDependencyDescriptor(
												desc, autowiredBeanName, field.getType());
									}
								}
							}
						}
						else {
							this.cachedFieldValue = null;
						}
						this.cached = true;
					}
				}
			}
			if (value != null) {
				ReflectionUtils.makeAccessible(field);
				field.set(bean, value);
			}
		}

这个方法做了3个流程,第一个流程是去创建依赖对象,通过value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);这句实现,第二个就是将返回的值做缓存处理;第三个就是反射set值。很明显依赖bean的实例化是在resolveDependency里面去完成的,接下来我们继续看这个方法到底是怎么完成bean的创建的,函数里面有很多流程判断,有些流程我也没弄明白到底为什么那么做,目前只弄明白了主要流程,所以我们直接进入到主流程里面,在resolveDependency里面会去调用doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter)这个方法,而这个方法就是依赖bean的主流程,这里面会去创建bean的操作,代码如下,我们来讲解下这里面的具体实现:

public Object doResolveDependency(DependencyDescriptor descriptor, String beanName,
			Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {

		InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
		try {
			Object shortcut = descriptor.resolveShortcut(this);
			if (shortcut != null) {
				return shortcut;
			}

			Class<?> type = descriptor.getDependencyType();
			Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
			if (value != null) {
				if (value instanceof String) {
					String strVal = resolveEmbeddedValue((String) value);
					BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
					value = evaluateBeanDefinitionString(strVal, bd);
				}
				TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
				return (descriptor.getField() != null ?
						converter.convertIfNecessary(value, type, descriptor.getField()) :
						converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
			}

			Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
			if (multipleBeans != null) {
				return multipleBeans;
			}

			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
			if (matchingBeans.isEmpty()) {
				if (isRequired(descriptor)) {
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				return null;
			}

			String autowiredBeanName;
			Object instanceCandidate;

			if (matchingBeans.size() > 1) {
				autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
				if (autowiredBeanName == null) {
					if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
						return descriptor.resolveNotUnique(type, matchingBeans);
					}
					else {
						// In case of an optional Collection/Map, silently ignore a non-unique case:
						// possibly it was meant to be an empty collection of multiple regular beans
						// (before 4.3 in particular when we didn't even look for collection beans).
						return null;
					}
				}
				instanceCandidate = matchingBeans.get(autowiredBeanName);
			}
			else {
				// We have exactly one match.
				Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
				autowiredBeanName = entry.getKey();
				instanceCandidate = entry.getValue();
			}

			if (autowiredBeanNames != null) {
				autowiredBeanNames.add(autowiredBeanName);
			}
			return (instanceCandidate instanceof Class ?
					descriptor.resolveCandidate(autowiredBeanName, type, this) : instanceCandidate);
		}
		finally {
			ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
		}
	}

首先,会先判断这个对象是不是@Value注解的,如果是就是去执行value解析,解析出value的值直接返回,如下就是value的处理:

Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
			if (value != null) {
				if (value instanceof String) {
					String strVal = resolveEmbeddedValue((String) value);
					BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
					value = evaluateBeanDefinitionString(strVal, bd);
				}
				TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
				return (descriptor.getField() != null ?
						converter.convertIfNecessary(value, type, descriptor.getField()) :
						converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
			}

如果不是@Value的话,那么就进入到解析bean的过程,下面这个是解析多重bean的(这个多重bean概念还没搞清楚是什么,看具体实现好像是个集合,集合里面有不同的元素,这些元素的type是不一样的)

Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
			if (multipleBeans != null) {
				return multipleBeans;
			}

接着如果不是多重bean对象,则会去匹配单个的bean:

Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);

如果匹配到多个的话就会通过一种策略去决策哪个bean来注入,具体不张开讲,不懂。找到了bean definition后,如果是个Class的话就会去执行创建bean的操作,又重新来一次bean创建流程不停的递归直到所有对象都创建完毕了就直接返回该实例对象。创建bean其实是下面这句代码做的:

descriptor.resolveCandidate(autowiredBeanName, type, this)

其实这里面的实现很简单就是调用beanFactory的getbean方法去实例化bean,如下:

public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
			throws BeansException {

		return beanFactory.getBean(beanName, requiredType);
	}

getBean里面又会执行bean的创建,bean创建后又会执行依赖注入流程,这样递归直到所有的依赖bean都创建实例完后,才返回最外层的bean并执行反射注入到目标bean里面。

猜你喜欢

转载自blog.csdn.net/wang5v/article/details/85005531
今日推荐