前言
Spring的依赖注入(DI):为某个对象的外部资源赋值,注入某个对象所需要的外部资源(包括对象、资源、常量数据等)。
依赖注入:Dependency Injection,简称DI,说白了就是利用反射机制为类的属性赋值的操作。
AutowiredAnnotationBeanPostProcessor是一个bean后置处理器,主要用于对@Autowired和@Value注解解析
一、 @Autowired的实际应用
@Autowired是spring用来进行内部注入的:他注入的值必须存在spring容器中
集合对象注入的查询过程
如果是数组或容器类型的话,Spring可以将所有与目标类型匹配的bean实例都注入进去,不需要判断
public class Father {
@Autowired
private List<Son> stringSon;
@Configuration
public class RootConfig {
@Bean
public List<Son> sonList(){
return new ArrayList<>();
}
@Bean
public Son son1(){
return new Son();
}
@Bean
public Son son2(){
return new Son();
}
}
容器启动中,spring会将son1和son2加入Father的stringSon集合中。但是son1和son2在stringSon集合的顺序遵循容器中相应目标bean定义的注册顺序,如果我们想使数组或列表中的项目以特定顺序排序,则可以使用@Order
或标准@Priority
@Order
:默认是最低优先级,值越小优先级越高
@Order(2)
@Bean
public Son son1(){
//...忽略代码
}
@Order(1)
@Bean
public Son son2(){
//...忽略代码
}
普通javaBean对象注入的查询过程
1、首先在容器中查询对应类型的bean ,如果查询结果刚好为一个,就将该bean装配给@Autowired指定的数据
2、如果查询的结果为空,那么会抛出异常。解决方法时,使用required=false
3、如果容器中存在多个同种类型bean,那就装配别名相同的,如果找不到别名相同的在这种情况下@Autowired(required=false)也会报错。
非集合范性对象注入的查询过程
1、首先在容器中查询对应类型和范性的bean ,如果查询结果刚好为一个,就将该bean装配给@Autowired指定的数据
2、如果查询的结果为空,那么会抛出异常。解决方法时,使用required=false
3、如果容器中存在多个同种类型和范性bean,那就装配别名相同的,如果找不到别名相同的在这种情况下@Autowired(required=false)也会报错。
这种情况的解决方法目前有2种
1、使用 @Qualifier直接点名要哪个
@Qualifier("car1")
@Autowired
private Car car;
2、@Primary 告诉spring容器,如果进行自动装配,那么优先选这个bean
- 注意:@Primary只能标注到一个同类型的Bean上
@Primary
@Bean
public Car car2(){
Car car = new Car();
car.setName("大众");
return car;
}
标注@Autowired注解的位置对spring对影响
1、标注在构造器上
从Spring Framework4.3开始,@Autowired如果目标bean仅定义一个构造函数作为开始,则不再需要在此类构造函数上添加注释。但是,如果有多个构造函数可用,则必须至少注释一个构造函数,@Autowired以指示容器使用哪个构造函数。
如果我们想spring生产bean的实例时,不要用无参构造器,那么只需在我们想要的执行的构造器上加上@Autowired
其形参是从spring容器中注入,如果spring容器没有其形参值的注入就报错,比如这样
public Father(){
System.out.println("Father...init")
}
@Autowired
public Father( Son son){
System.out.println("Father.String name..init");
}
这时我们可以使用@Autowired(required=false),这时如果spring容器没有son,那么spring初始化对象就会使用无参构造器,如果我还想使用有参构造器,这时我们需这样写
@Autowired
public Father(@Nullable Son son){
System.out.println("Father.String name..init")
}
spring容器没有son,也会执行这个构造器,注意:@Nullable只有在spring注入时才有这个效果,其他情况下是做提示用的
2、标注在方法上
Spring会先实例化所有Bean,然后根据配置进行扫描,当检测到@Autowired后进行注入,注入时调用这个方法。
3、标注在方法形参上和标准在类的成员属性上
如果放在形参旁边,表示此参数赋值是从IOC容器中寻找(4.3才有),如果此方法上有@Bean注解,则可以省略@Autowired
Spring创建当前类对象,就会调用此方法完成方法参数的赋值,方法参数的赋值是从IOC容器中寻找
二、AutowiredAnnotationBeanPostProcessor类说明
public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
//储存AutowiredAnnotationBeanPostProcessor解析的注解,默认有@Autowired和@Value
private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4);
private String requiredParameterName = "required";
private boolean requiredParameterValue = true;
private int order = Ordered.LOWEST_PRECEDENCE - 2;
@Nullable
private ConfigurableListableBeanFactory beanFactory;
private final Set<String> lookupMethodsChecked = Collections.newSetFromMap(new ConcurrentHashMap<>(256));
private final Map<Class<?>, Constructor<?>[]> candidateConstructorsCache = new ConcurrentHashMap<>(256);
//储存,解析@AutoWired和@Value的属性或方法生成的InjectionMetadata
private final Map<String, InjectionMetadata> injectionMetadataCache = new ConcurrentHashMap<>(256);
/**
* 默认支持@Autowired和@Value注解
* 如果导入了javax.inject.Inject,那么也支持@Inject注解
*/
@SuppressWarnings("unchecked")
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.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
从这篇文章SpringBean注册之后置处理器BeanPostProcessor,我们简要说下AutowiredAnnotationBeanPostProcessor各个方法的执行顺序
因为AutowiredAnnotationBeanPostProcessor是一个InstantiationAwareBeanPostProcessor,但其postProcessBeforeInstantiation为null,所以他不行影响spring内部正常的bean实例化流程。在调用bean的构造器后,又因为其是一个MergedBeanDefinitionPostProcessor,所以他会其postProcessMergedBeanDefinition,接着我们来到bean的赋值流程populateBean,其方法postProcessAfterInstantiation返回的是true,所以他会调用其postProcessProperties方法为bean赋值属性,最后其postProcessBeforeInitialization和postProcessAfterInitialization都是直接返回bean的
public abstract class InstantiationAwareBeanPostProcessorAdapter implements SmartInstantiationAwareBeanPostProcessor {
@Override
@Nullable
public Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
@Override
@Nullable
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
@Override
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
return bean;
}
@Override
@Nullable
//postProcessBeforeInstantiation为null,所以他不行影响spring内部正常的bean实例化流程
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
throws BeansException {
return null;
}
@Deprecated
@Override
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
return pvs;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
三、解析@AutoWired和@Value的属性或方法,把其封装成InjectionMetadata类
该过程发生在doCreateBean
的applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
片段中。
因为AutowiredAnnotationBeanPostProcessor
是一个MergedBeanDefinitionPostProcessor
,所以他会执行其postProcessMergedBeanDefinition
方法
public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition,Class<?> beanType, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
private InjectionMetadata findAutowiringMetadata(String beanName, 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 = buildAutowiringMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
//解析属性
ReflectionUtils.doWithLocalFields(targetClass, field -> {
//解析当前对象属性,判断其是否有@Autowired和@value注解,如果有返回其注解对象
AnnotationAttributes 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);
//把当前属性封装成AutowiredFieldElement对象储存到injectionMetadataCache中
currElements.add(new AutowiredFieldElement(field, required));
}
});
//解析方法
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
//解析当前对象属性,判断其是否有@Autowired和@value注解,如果有返回其注解对象
AnnotationAttributes 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);
//把当前方法封装成AutowiredMethodElement对象储存到injectionMetadataCache中
currElements.add(new AutowiredMethodElement(method, required, pd));
}
});
elements.addAll(0, currElements);
//开始解析其父类
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return new InjectionMetadata(clazz, elements);
}
}
1、解析当前bean的属性,静态属性不解析。把当前属性封装成AutowiredFieldElement对象储存到currElements
中
2、解析当前bean的方法,静态方法和无参方法不解析。把当前属性封装成AutowiredMethodElement对象储存到currElements
中
3、把currElements
集合封装成一个InjectionMetadata
对象储存到injectionMetadataCache
中,如下
public class InjectionMetadata {
private static final Log logger = LogFactory.getLog(InjectionMetadata.class);
private final Class<?> targetClass;
private final Collection<InjectedElement> injectedElements;
四、赋值标注@AutoWired和@Value的属性或方法
public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
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;
}
}
InjectionMetadata底层的inject方法是遍历其属性injectedElements集合中的InjectedElement的inject方法。从上面的分析我们字段,方法会被封装成AutowiredMethodElement对象。属性封装成AutowiredFieldElement对象。
public class InjectionMetadata {
private final Class<?> targetClass;
private final Collection<InjectedElement> injectedElements;
private volatile Set<InjectedElement> checkedElements;
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);
}
}
}
4.1 属性的装配
private class AutowiredFieldElement extends InjectionMetadata.InjectedElement {
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable{
// 显然此处父类的member就指的是filed
Field field = (Field) this.member;
Object value;
// 走缓存,关于cachedFieldValue的值
if (this.cached) {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
else {
// 每个Field都包装成一个DependencyDescriptor
// 如果是Method包装成DependencyDescriptor,毕竟一个方法可以有多个入参
// 此处包装成它后,显然和元数据都无关了,只和Field有关了 完全隔离
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
Assert.state(beanFactory != null, "No BeanFactory available");
// 转换器使用的bean工厂的转换器~~~
TypeConverter typeConverter = beanFactory.getTypeConverter();
try {
// 获取依赖的value值的工作 最终还是委托给beanFactory.resolveDependency()去完成的~~~~
//到容器中查询要装配的值,这是自动装配的核心方法。后面出一片文章单独讲解
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
// 下面代码是把缓存值缓存起来 让同一个Field注入多次能提高效率
synchronized (this) {
if (!this.cached) {
// 可以看到value!=null并且required=true才会进行缓存的处理
if (value != null || this.required) {
this.cachedFieldValue = desc;
// 简单的说就是注册到bean工厂去,比如此处b是依赖a的 所以就注册这个依赖关系进去了
// 参考this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
registerDependentBeans(beanName, autowiredBeanNames);
// autowiredBeanNames里可能会有别名的名称~~~所以size可能大于1
if (autowiredBeanNames.size() == 1) {
// beanFactory.isTypeMatch挺重要的~~~~因为@Autowired是按照类型注入的
String autowiredBeanName = autowiredBeanNames.iterator().next();
//如果容器中包含这个bean的名字,且类型一样
if (beanFactory.containsBean(autowiredBeanName) &&beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
this.cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
else {
this.cachedFieldValue = null;
}
this.cached = true;
}
}
}
// 不为null,就完成最终的set值 利用反射给filed属性赋值~~~~
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
}
4.2 方法的装配
private class AutowiredMethodElement extends InjectionMetadata.InjectedElement {
@Override
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) {
// Shortcut for avoiding synchronization...
arguments = resolveCachedArguments(beanName);
}
else {
Class<?>[] paramTypes = method.getParameterTypes();
arguments = new Object[paramTypes.length];
DependencyDescriptor[] descriptors = new DependencyDescriptor[paramTypes.length];
Set<String> autowiredBeans = new LinkedHashSet<>(paramTypes.length);
Assert.state(beanFactory != null, "No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter();
for (int i = 0; i < arguments.length; i++) {
MethodParameter methodParam = new MethodParameter(method, i);
DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required);
currDesc.setContainingClass(bean.getClass());
descriptors[i] = currDesc;
try {
//到容器中查询要装配的值,这是自动装配的核心方法。后面出一片文章单独讲解
Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);
if (arg == null && !this.required) {
arguments = null;
break;
}
arguments[i] = arg;
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(methodParam), ex);
}
}
synchronized (this) {
if (!this.cached) {
if (arguments != null) {
Object[] cachedMethodArguments = new Object[paramTypes.length];
System.arraycopy(descriptors, 0, cachedMethodArguments, 0, arguments.length);
registerDependentBeans(beanName, autowiredBeans);
if (autowiredBeans.size() == paramTypes.length) {
Iterator<String> it = autowiredBeans.iterator();
for (int i = 0; i < paramTypes.length; i++) {
String autowiredBeanName = it.next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
cachedMethodArguments[i] = new ShortcutDependencyDescriptor(
descriptors[i], autowiredBeanName, paramTypes[i]);
}
}
}
this.cachedMethodArguments = cachedMethodArguments;
}
else {
this.cachedMethodArguments = null;
}
this.cached = true;
}
}
}
if (arguments != null) {
try {
ReflectionUtils.makeAccessible(method);
method.invoke(bean, arguments);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
五、容器是怎么获取要装配的值
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactoryimplements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
// 把当前Bean工厂的名字发现器赋值给传进来DependencyDescriptor 类
// 这里面注意了:有必要说说名字发现器这个东西,具体看下面吧==========还是比较重要的
// Bean工厂的默认值为:private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
// 支持到Optional类型的注入,比如我们这样注入:private Optional<GenericBean<Object, Object>> objectGenericBean;
// 也是能够注入进来的,只是类型变为,Optional[GenericBean(t=obj1, w=2)]
// 对于Java8中Optional类的处理
if (Optional.class == descriptor.getDependencyType()) {
return createOptionalDependency(descriptor, requestingBeanName);
}
// 兼容ObjectFactory和ObjectProvider(Spring4.3提供的接口)
// 关于ObjectFactory和ObjectProvider在依赖注入中的大作用,我觉得是非常有必要再撰文讲解的
//对于前面讲到的提早曝光的ObjectFactory的特殊处理
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
// 支持到了javax.inject.Provider这个类的实现
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName);
}
// 这个应该是我们觉得部分触及到的,其实不管何种方式,最终都是交给doResolveDependency方法去处理了
else {
//getAutowireCandidateResolver()得到ContextAnnotationAutowireCandidateResolver 根据依赖注解信息,找到对应的Bean值信息
//getLazyResolutionProxyIfNecessary方法,它也是唯一实现。
//如果字段上带有@Lazy注解,表示进行懒加载 Spring不会立即创建注入属性的实例,而是生成代理对象,来代替实例
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
// 这里如果不是懒加载的(绝大部分情况都走这里) 就进入核心方法doResolveDependency 下面有分解
if (result == null) {
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
5.1 获取要装配的值
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
// 相当于打个点,记录下当前的步骤位置 返回值为当前的InjectionPoint
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
// 简单的说就是去Bean工厂的缓存里去看看,有没有名称为此的Bean,有就直接返回,没必要继续往下走了
// 比如此处的beanName为:objectGenericBean等等
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
Class<?> type = descriptor.getDependencyType();
//处理@Value
//3.1 获取@Value中的值value
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
//3.2 解析value
if (value instanceof String) {
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
value = evaluateBeanDefinitionString(strVal, bd);
}
//3.3 value转换类型后返回
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()));
}
}
//4. 处理数组和Collections类型
//因为是数组或容器,Sprng可以直接把符合类型的bean都注入到数组或容器中,处理逻辑是:
//4.1 确定容器或数组的组件类型
//4.2 调用findAutowireCandidates方法,获取与组件类型匹配的Map(beanName -> bean实例)
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
// 获取所有【类型】匹配的Beans,形成一个Map(此处用Map装,是因为可能不止一个符合条件)
// 该方法就特别重要了,对泛型类型的匹配、对@Qualifierd的解析都在这里面,下面详情分解
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
//6. 结果为空的时候,如果设置的是required,也要抛出异常
if (matchingBeans.isEmpty()) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
// 若有多个匹配
// 需要注意的是:@Qualifier注解在上面就已经生效了~~~~因为AutowireCandidateResolver.isAutowireCandidate是在上面生效的
if (matchingBeans.size() > 1) {
// 由它进行判别 从弱水三千中 取出一瓢
// 1、是否标注有@Primary 有这种bean就直接返回(@Primary只允许标注在一个同类型Bean上)
// 2、看是否有标注有`javax.annotation.Priority`这个注解的
// 3、根据字段field名,去和beanName匹配 匹配上了也行(这就是为何我们有时候不用@Qulifier也没事的原因之一)
// 此处注意:descriptor.getDependencyName()这个属性表示字段名,靠的是`DefaultParameterNameDiscoverer`去把字段名取出来的~
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 {
// 仅仅只匹配上一个,走这里 很简单 直接拿出来即可
// 注意这里直接拿出来的技巧:不用遍历,直接用iterator.next()即可
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
// 把找到的autowiredBeanName 放进去
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
// 底层就是调用了beanFactory.getBean(beanName); 确保该实例肯定已经被实例化了的
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;
}
// 再一次校验,type和result的type类型是否吻合=====
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
return result;
}
// 最终把节点归还回来
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
5.2 获取要装配的值后,怎么确定要装配那个值
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
Class<?> requiredType = descriptor.getDependencyType();
// 看看传入的Bean中有没有标注了@Primary注解的
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
// 如果找到了 就直接返回
// 由此可见,@Primary的优先级还是非常的高的
if (primaryCandidate != null) {
return primaryCandidate;
}
//找到一个标注了javax.annotation.Priority注解的。(备注:优先级的值不能有相同的,否则报错)
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null) {
return priorityCandidate;
}
// Fallback
// 这里是最终的处理(相信绝大部分情况下,都会走这里~~~~~~~~~~~~~~~~~~~~)
// 此处就能看出resolvableDependencies它的效能了,他会把解析过的依赖们缓存起来,不用再重复解析了
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateName = entry.getKey();
Object beanInstance = entry.getValue();
// 到这一步就比较简单了,matchesBeanName匹配上Map的key就行。
// 需要注意的是,bean可能存在很多别名,所以只要有一个别名相同,就认为是能够匹配上的 具体参考AbstractBeanFactory#getAliases方法
//descriptor.getDependencyName() 这个特别需要注意的是:如果是字段,这里调用的this.field.getName() 直接用的是字段的名称
// 因此此处我们看到的情况是,我们采用@Autowired虽然匹配到两个类型的Bean了,即使我们没有使用@Qualifier注解,也会根据字段名找到一个合适的(若没找到,就抱错了)
if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
matchesBeanName(candidateName, descriptor.getDependencyName())) {
return candidateName;
}
}
return null;
}