什么是spring bean装配 Bean的装配可以理解为依赖关系注入,Bean的装配方式即Bean依赖注入的方式。
spring 容器加载bean定义方式 1.xml
2.注解
bean装配方式 xml 标签中定义了autowite属性
No 缺省情况下,自动配置是通过“ref”属性手动设定,在项目中最常用。
byName 根据属性名称自动装配。如果一个bean的名称和其他的bean属性的名称是一样的,将会装配它。
byType 按类型自动装配,如果bean的数据类型是用其它bean属性的数据类型,兼容并自动装配它。
Constructor 在构造函数参数的byType方式。
autodetect 如果找到默认的构造函数,使用“自动装配用构造”;否则,使用“按类型自动装配”
注解 版本 1 <spring-framework.version > 5.2.12.RELEASE</spring-framework.version >
关注点 @Resource @Autowired
源码 1 2 3 4 5 6 7 8 9 10 SpringApplication.run(ServiceBApplication.class, args); refreshContext(context); refresh((ApplicationContext) context); AbstractApplicationContext.refresh(); finishBeanFactoryInitialization(beanFactory); beanFactory.preInstantiateSingletons(); doGetBean(); createBean(); populateBean(beanName, mbd, instanceWrapper);PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
@Resource 对应着 CommonAnnotationBeanPostProcessor
@Autowired 对应着 AutowiredAnnotationBeanPostProcessor
@resource CommonAnnotationBeanPostProcessor postProcessProperties方法
1 InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 private InjectionMetadata findResourceMetadata (String beanName, final Class<?> clazz, @Nullable PropertyValues pvs) { String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName()); 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); } metadata = buildResourceMetadata(clazz); this .injectionMetadataCache.put(cacheKey, metadata); } } } return metadata; }
1 2 3 4 5 6 7 8 9 private InjectionMetadata buildResourceMetadata (final Class<?> clazz) ; else if (field.isAnnotationPresent(Resource.class)) { if (Modifier.isStatic(field.getModifiers())) { throw new IllegalStateException ("@Resource annotation is not supported on static fields" ); } if (!this .ignoredResourceTypes.contains(field.getType().getName())) { currElements.add(new ResourceElement (field, field, null )); } }
看到这里发现ResourceElement。关注类中name和lookupType
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public ResourceElement (Member member, AnnotatedElement ae, @Nullable PropertyDescriptor pd) { super (member, pd); Resource resource = ae.getAnnotation(Resource.class); String resourceName = resource.name(); Class<?> resourceType = resource.type(); this .isDefaultName = !StringUtils.hasLength(resourceName); if (this .isDefaultName) { resourceName = this .member.getName(); if (this .member instanceof Method && resourceName.startsWith("set" ) && resourceName.length() > 3 ) { resourceName = Introspector.decapitalize(resourceName.substring(3 )); } } else if (embeddedValueResolver != null ) { resourceName = embeddedValueResolver.resolveStringValue(resourceName); } if (Object.class != resourceType) { checkResourceType(resourceType); } else { resourceType = getResourceType(); } this .name = (resourceName != null ? resourceName : "" ); this .lookupType = resourceType; String lookupValue = resource.lookup(); this .mappedName = (StringUtils.hasLength(lookupValue) ? lookupValue : resource.mappedName()); Lazy lazy = ae.getAnnotation(Lazy.class); this .lazyLookup = (lazy != null && lazy.value()); }
找到InjectionMetadata后:
1 metadata.inject(bean, beanName, pvs);
1 2 3 4 5 6 7 8 9 10 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); } } }
会调用ResourceElement的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 protected void inject (Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs) throws Throwable { if (this .isField) { Field field = (Field) this .member; ReflectionUtils.makeAccessible(field); field.set(target, getResourceToInject(target, requestingBeanName)); } else { if (checkPropertySkipping(pvs)) { return ; } try { Method method = (Method) this .member; ReflectionUtils.makeAccessible(method); method.invoke(target, getResourceToInject(target, requestingBeanName)); } catch (InvocationTargetException ex) { throw ex.getTargetException(); } } }
1 2 3 4 5 @Override protected Object getResourceToInject (Object target, @Nullable String requestingBeanName) { return (this .lazyLookup ? buildLazyResourceProxy(this , requestingBeanName) : getResource(this , requestingBeanName)); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 protected Object getResource (LookupElement element, @Nullable String requestingBeanName) throws NoSuchBeanDefinitionException { if (StringUtils.hasLength(element.mappedName)) { return this .jndiFactory.getBean(element.mappedName, element.lookupType); } if (this .alwaysUseJndiLookup) { return this .jndiFactory.getBean(element.name, element.lookupType); } if (this .resourceFactory == null ) { throw new NoSuchBeanDefinitionException (element.lookupType, "No resource factory configured - specify the 'resourceFactory' property" ); } return autowireResource(this .resourceFactory, element, requestingBeanName); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 protected Object autowireResource (BeanFactory factory, LookupElement element, @Nullable String requestingBeanName) throws NoSuchBeanDefinitionException { Object resource; Set<String> autowiredBeanNames; String name = element.name; if (factory instanceof AutowireCapableBeanFactory) { AutowireCapableBeanFactory beanFactory = (AutowireCapableBeanFactory) factory; DependencyDescriptor descriptor = element.getDependencyDescriptor(); if (this .fallbackToDefaultTypeMatch && element.isDefaultName && !factory.containsBean(name)) { autowiredBeanNames = new LinkedHashSet <>(); resource = beanFactory.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, null ); if (resource == null ) { throw new NoSuchBeanDefinitionException (element.getLookupType(), "No resolvable resource object" ); } } else { resource = beanFactory.resolveBeanByName(name, descriptor); autowiredBeanNames = Collections.singleton(name); } } else { resource = factory.getBean(name, element.lookupType); autowiredBeanNames = Collections.singleton(name); } if (factory instanceof ConfigurableBeanFactory) { ConfigurableBeanFactory beanFactory = (ConfigurableBeanFactory) factory; for (String autowiredBeanName : autowiredBeanNames) { if (requestingBeanName != null && beanFactory.containsBean(autowiredBeanName)) { beanFactory.registerDependentBean(autowiredBeanName, requestingBeanName); } } } return resource; }
@Resource 在不指定 name 的情况下,默认是按 field 的 name 来注入的;如果按默认的 name 找不到 bean,则会按 type 注入
@Autowired AutowiredAnnotationBeanPostProcessor
1 2 3 4 5 6 7 @Deprecated @Override public PropertyValues postProcessPropertyValues ( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) { return postProcessProperties(pvs, bean, beanName); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Override 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; }
找到 AutowiredFieldElement AutowiredMethodElement
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 @Override protected void inject (Object bean, @Nullable String beanName, @Nullable 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 <>(1 ); Assert.state(beanFactory != null , "No BeanFactory available" ); 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) { Object cachedFieldValue = null ; if (value != null || this .required) { cachedFieldValue = desc; registerDependentBeans(beanName, autowiredBeanNames); if (autowiredBeanNames.size() == 1 ) { String autowiredBeanName = autowiredBeanNames.iterator().next(); if (beanFactory.containsBean(autowiredBeanName) && beanFactory.isTypeMatch(autowiredBeanName, field.getType())) { cachedFieldValue = new ShortcutDependencyDescriptor ( desc, autowiredBeanName, field.getType()); } } } this .cachedFieldValue = cachedFieldValue; this .cached = true ; } } } if (value != null ) { ReflectionUtils.makeAccessible(field); field.set(bean, value); } } }
1 value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 @Override @Nullable public Object resolveDependency (DependencyDescriptor descriptor, @Nullable String requestingBeanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException { descriptor.initParameterNameDiscovery(getParameterNameDiscoverer()); if (Optional.class == descriptor.getDependencyType()) { return createOptionalDependency(descriptor, requestingBeanName); } else if (ObjectFactory.class == descriptor.getDependencyType() || ObjectProvider.class == descriptor.getDependencyType()) { return new DependencyObjectProvider (descriptor, requestingBeanName); } else if (javaxInjectProviderClass == descriptor.getDependencyType()) { return new Jsr330Factory ().createDependencyProvider(descriptor, requestingBeanName); } else { Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary( descriptor, requestingBeanName); if (result == null ) { result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter); } return result; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 @Nullable 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) { 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(descriptor.getResolvableType(), matchingBeans); } else { return null ; } } instanceCandidate = matchingBeans.get(autowiredBeanName); } else { 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); } }
@Autowired 的装配顺序:
1.按 type 在上下文中查找匹配的 bean 2.如果有多个bean,则按 name 进行匹配 2.1 如果有 @Qualifier 注解,则按照 @Qualifier 指定的name进行匹配 2.2 如果没有,则按照 field 的 name 进行匹配 3. 匹配不到,则报错。 如果设置 @Autowired(required=false),则注入失败时不会抛出异常