Principio de anotación Spring @Autowired

Principio de anotación Spring @Autowired

1. Usos de @Autowired

@ComponentScan("org.example.bean")
public class AnnoContextDemo {

    @Autowired
    private User user;


    public static void main(String[] args) {

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AnnoContextDemo.class);

        User user1 = context.getBean(AnnoContextDemo.class).user;

        System.out.println("user1 = " + user1);
    }


}

Clase de configuración de componente escaneado

@Configuration
public class BeanConfig {

    @Bean
    public User user(){
        return new User(21,"张三");
    }

}

resultado de salida

user1 = User{age=21, name='张三'}

2. Principio de inyección automática de dependencia

Localice el paquete org.springframework.beans.factory.annotation.Autowired donde se encuentra @Autowired

Encuentre AutowiredAnnotationBeanPostProcessor en el mismo paquete

imagen-20230717202302872

El diagrama de herencia de clases de AutowiredAnnotationBeanPostProcessor es el siguiente

imagen-20230717202419423

AutowiredAnnotationBeanPostProcessor implementa InstantiationAwareBeanPostProcessor con

MergedBeanDefinitionPostProcessor dos interfaces de posprocesador BeanPostProcessor

  1. MergedBeanDefinitionPostProcessor Esta interfaz tiene principalmente dos métodos método abstracto postProcessMergedBeanDefinition método predeterminado resetBeanDefinition

  2. InstantiationAwareBeanPostProcessor Este método abstracto de interfaz postProcessBeforeInstantiation, postProcessAfterInstantiation, método predeterminado postProcessProperties, método obsoleto predeterminado postProcessPropertyValues

Si desea comprender el principio de la inyección @Autowried, primero debe conocer el orden en que se ejecutan los métodos correspondientes de estas interfaces y realizar un seguimiento del método ApplicationContext.refresh. El enlace de la llamada es el siguiente

ApplicationContext.refresh() -> AbstractApplicationContext.finishBeanFactoryInitialization() -> ConfigurableListableBeanFactory.preInstantiateSingletons() -> AbstractBeanFactory.getBean() -> AbstractBeanFactory.doGetBean() -> AbstractBeanFactory.getSingleton() -> AbstractBeanFactory.createBean()

antes de la instanciación

-> resolveBeforeInstantiation() Ejecuta el método previo InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation() Si el valor devuelto no es nulo, se ejecutará el método posterior InstationAwareBeanPostProcessor.postProcessAfterInitialization().

Crear fase de instancia de bean

-> doCreateBean() -> createBeanInstance reflejo crea una instancia de bean

-> applyMergedBeanDefinitionPostProcessors() Ejecute el método MergedBeanDefinitionPostProcessor.MergedBeanDefinitionPostProcessor para fusionar la información de definición de bean

Fase de inyección de atributos

-> populateBean() -> ejecutar InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation método de posprocesamiento -> ejecutar InstatiationAwareBeanPostProcessor.postProcessProperties -> InstatiationAwareBeanPostProcessor.postProcessPropertyValues ​​-> applyPropertyValues ​​ejecutar inyección de propiedades

fase de inicialización

-> initializeBean() -> BeanPostProcessor.postProcessBeforeInitialization() Ejecutar el método previo -> invocarInitMethods() Llamar reflexivamente al método de inicialización -> BeanPostProcessor.postProcessAfterInitialization Ejecutar el método posterior

Bean de registro de cierre

->registerDisposableBeanIfNecessary() Registrar bean

Al rastrear el método refresh () anterior, podemos ver que el contenedor de primavera primero llamará al método AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition y luego ejecutará el método postProcessProperties

3. postProcessMergedBeanDefinition encuentra los campos o métodos que deben inyectarse automáticamente

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

Ingrese el método findAutowiringMetadata

	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);
					}
					//查找类的字段,方法,是否有需要自动注入对象的元素,封装InjectionMetadata
					metadata = buildAutowiringMetadata(clazz);
					//放入缓存中,供后面调用取出
					this.injectionMetadataCache.put(cacheKey, metadata);
				}
			}
		}
		return metadata;
	}

Ingrese el método buildAutowiringMetadata

private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {
		//判断当前类是否有使用autowiredAnnotationTypes容器中的注解
		if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
			return InjectionMetadata.EMPTY;
		}

		List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
		Class<?> targetClass = clazz;

		do {
			final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
			//反射遍历类中所有字段
			ReflectionUtils.doWithLocalFields(targetClass, field -> {
				//字段上是否有标注自动装配相关的注解
				MergedAnnotation<?> ann = findAutowiredAnnotation(field);
				if (ann != null) {
					if (Modifier.isStatic(field.getModifiers())) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation is not supported on static fields: " + field);
						}
						return;
					}
					boolean required = determineRequiredStatus(ann);
					//封装InjectionMetadata
					currElements.add(new AutowiredFieldElement(field, required));
				}
			});
			
			//反射遍历类中所有方法
			ReflectionUtils.doWithLocalMethods(targetClass, method -> {
				Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
				if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
					return;
				}
					//方法上是否有标注自动装配相关的注解
				MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
				if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
					if (Modifier.isStatic(method.getModifiers())) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation is not supported on static methods: " + method);
						}
						return;
					}
					if (method.getParameterCount() == 0) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation should only be used on methods with parameters: " +
									method);
						}
					}
					boolean required = determineRequiredStatus(ann);
					PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
					//封装InjectionMetadata
					currElements.add(new AutowiredMethodElement(method, required, pd));
				}
			});

			elements.addAll(0, currElements);
			targetClass = targetClass.getSuperclass();
		}
		while (targetClass != null && targetClass != Object.class);

		return InjectionMetadata.forElements(elements, clazz);
	}

this.autowiredAnnotationTypes es una colección establecida, y el contenedor es una clase de anotación que debe inyectarse automáticamente

private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4);
	public AutowiredAnnotationBeanPostProcessor() {
	## 1.@Autowired
		this.autowiredAnnotationTypes.add(Autowired.class);
  ## 2.@Value
		this.autowiredAnnotationTypes.add(Value.class);
		try {
 ## [email protected]  JSR-330规范中定义的一个注解
			this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
					ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
			logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
		}
		catch (ClassNotFoundException ex) {
			// JSR-330 API not available - simply skip.
		}
	}

4.postProcessProperties Los elementos que deben inyectarse automáticamente obtienen el bean del contenedor y lo inyectan

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

Introduzca el método metadata.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) {
				//不同类型调用各自inject方法
				element.inject(target, beanName, pvs);
			}
		}
	}

lógica de procesamiento de campos

A través del método resolveFieldValue, encuentre el bean (único o de colección) del que se debe depender e inyéctelo a través del método Filed.set

		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-resolve
					value = resolveFieldValue(field, bean, beanName);
				}
			}
			else {
			//查找依赖的bean
				value = resolveFieldValue(field, bean, beanName);
			}
			if (value != null) {
				ReflectionUtils.makeAccessible(field);
				//反射设置值
				field.set(bean, value);
			}
		}

public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable 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());
				try {
					return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
				}
				catch (UnsupportedOperationException ex) {
					// A custom TypeConverter which does not support TypeDescriptor resolution...
					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;
			}

			//字段非集合类型时bean时查找方法
			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(descriptor.getResolvableType(), 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);
			}
			if (instanceCandidate instanceof Class) {
				instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
			}
			Object result = instanceCandidate;
			if (result instanceof NullBean) {
				if (isRequired(descriptor)) {
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				result = null;
			}
			if (!ClassUtils.isAssignableValue(type, result)) {
				throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
			}
			return result;
		}
		finally {
			ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
		}
	}

findAutowireCandidates() llamará a BeanFactoryUtils.beanNamesForTypeInclusiveAncestors

La capa inferior encuentra todos los beans a través de un modelo de delegación parental similar

	public static String[] beanNamesForTypeIncludingAncestors(
			ListableBeanFactory lbf, Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {

		Assert.notNull(lbf, "ListableBeanFactory must not be null");
		String[] result = lbf.getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
		if (lbf instanceof HierarchicalBeanFactory) {
			HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;
			if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
				String[] parentResult = beanNamesForTypeIncludingAncestors(
						(ListableBeanFactory) hbf.getParentBeanFactory(), type, includeNonSingletons, allowEagerInit);
				result = mergeNamesWithParent(result, parentResult, hbf);
			}
		}
		return result;
	}

Supongo que te gusta

Origin blog.csdn.net/JAVAlife2021/article/details/131775513
Recomendado
Clasificación