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
El diagrama de herencia de clases de AutowiredAnnotationBeanPostProcessor es el siguiente
AutowiredAnnotationBeanPostProcessor implementa InstantiationAwareBeanPostProcessor con
MergedBeanDefinitionPostProcessor dos interfaces de posprocesador BeanPostProcessor
-
MergedBeanDefinitionPostProcessor Esta interfaz tiene principalmente dos métodos método abstracto postProcessMergedBeanDefinition método predeterminado resetBeanDefinition
-
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;
}