我们经常注入的方式是这样的@ServicepublicclassHelloService{@AutowiredprivateBeanFactorybeanFactory;@AutowiredpublicHelloService(ApplicationContextapplicationContext){}@AutowiredpublicvoidsetEnvironment(Environmentenvironment){}}无论是构造函数注入还是属性注入,我们都可以称之为显式注入。来看看我们常用的一个注解@Beanpublic@interfaceBean{@AliasFor("name")String[]value()default{};@AliasFor("value")String[]name()default{};@弃用的Autowireautowire()defaultAutowire.NO;布尔autowireCandidate()默认为真;StringinitMethod()默认"";StringdestroyMethod()defaultAbstractBeanDefinition.INFER_METHOD;}我们关心的属性autowire已经被弃用了,但这并不妨碍我们一探究竟。NO默认值,表示不自动注入BY_NAME,通过beanName自动注入BY_TYPE,自动注入参数类型Autowire.NO@ConfigurationpublicclassConfig{@Bean(autowire=Autowire.NO)publicHelloServicehelloService(){returnnewHelloService();}}publicclassHelloService{publicvoidsetEnvironment(Environmentenvironment){System.out.println("invoke"+environment);}}我们使用默认配置,不自动注入HelloService,毫无疑问,setEnvironment是不会被Spring框架调用的。Autowire.BY_NAME如果我们把上面的代码改成@Bean(autowire=Autowire.BY_NAME),就会发现调用了setEnvironment,参数environment是Spring中的StandardServletEnvironment。过程(3)可以知道在AbstractAutowireCapableBeanFactory#populateBean中调用了//将自动注入的值放入newPvsif(resolvedAutowireMode==AUTOWIRE_BY_NAME){autowireByName(beanName,mbd,bw,newPvs);}//如果适用,按类型添加基于自动装配的属性值。如果(resolvedAutowireMode==AUTOWIRE_BY_TYPE){autowireByType(beanName,mbd,bw);}pvs=newPvs;}............if(pvs!=null){applyPropertyValues(beanName,mbd,bw,pvs);}对应的代码也很简单protectedvoidautowireByName(StringbeanName,AbstractBeanDefinitionmbd,BeanWrapperbw,MutablePropertyValuespvs){//根据setter方法获取需要的值对于主要的beanName,解释setter方法String[]propertyNames=unsatisfiedNonSimpleProperties(mbd,bw);for(StringpropertyName:propertyNames){//如果不在BeanFactory中,直接忽略,不会报错if(containsBean(propertyName)){Objectbean=getBean(propertyName);//添加到pvspvs.add(propertyName,bean);registerDependentBean(propertyName,beanName);}else{//如果bean不存在,不报错,忽略即可}}}可以看到BY_NAME的方式是通过解析setter方法名获取需要注入的beanName。如果BeanFactory中不存在beanName,则直接忽略,类似于@Autowired(required=false)。不强制注入但是你的方法名必须以setXxx开头,符合一定的命名规则,类似于BeanInfo规则(Java自省),但比它宽松,这里的返回值没有限制必须是voidAutowire.BY_TYPEautowireByTypeprotectedvoidautowireByType(StringbeanName,AbstractBeanDefinitionmbd,BeanWrapperbw,MutablePropertyValuespvs){......SetautowiredBeanNames=newLinkedHashSet<>(4);String[]propertyNames=unsatisfiedNonSimpleProperties(mbd,bw);//遍历setter方法解释获取其属性名称for(StringpropertyName:propertyNames){try{PropertyDescriptorpd=bw.getPropertyDescriptor(propertyName);if(Object.class!=pd.getPropertyType()){方法参数methodParam=BeanUtils.getWriteMethodParameter(pd);booleaneager=!(bw.getWrappedInstance()instanceofPriorityOrdered);//AutowireByTypeDependencyDescriptor是关键类,其返回的getDependencyName始终为nullDependencyDescriptordesc=newAutowireByTypeDependencyDescriptor(methodParam,eager);对象autowiredArgument=resolveDependency(desc,beanName,autowiredBeanNames,转换器);if(autowiredArgument!=null){pvs.add(propertyName,autowiredArgument);}for(StringautowiredBeanName:autowiredBeanNames){registerDependentBean(autowiredBeanNamesautowiredBeanName)red,}beanclear();}}catch(BeansExceptionex){抛出新的UnsatisfiedDependencyException(mbd.getResourceDescription(),beanName,propertyName,ex);}}}和BY_NAME很像,如果我自动注入的对象在BeanFactory中不存在,会不会抛出异常呢?答案是的,这里主要是因为使用了这种AutowireByTypeDependencyDescriptorprivatestaticclassAutowireByTypeDependencyDescriptorextendsDependencyDescriptor{publicAutowireByTypeDependencyDescriptor(MethodParametermethodParameter,booleaneager){super(methodParameter,false,eager);}@OverridepublicStringgetDependencyName(){返回空值;}}//父类publicDependencyDescriptor(MethodParametermethodParameter,booleanrequired,booleaneager){super(methodParameter);.......this.required=required;......}First一个关键点是required为false,当依赖的bean没有BeanFactory时,false不会抛出异常第二个关键点是,如果有两个相同的bean,如果这两个bean都没有声明Primary或??PriorityOrderd,它仍然会抛出异常,而不是根据beanName过滤出合适的bean,因为getDependencyName总是返回null,这个情况和@Autowired不一样,因为BY_TYPE方法不依赖@NullableprotectedbeanNameStringprimaryCandidate=determinePrimaryCandidate(candidates,requiredType);如果(primaryCandidate!=null){返回primaryCandidate;}StringpriorityCandidate=determineHighestPriorityCandidate(candidates,requiredType);如果(priorityCandidate!=null){返回priorityCandidate;}//Fallbackfor(Map.Entryentry:candidates.entrySet()){StringcandidateName=entry.getKey();对象beanInstance=entry.getValue();//resolvableDependenciesif((beanInstance!=null&&this.resolvableDedependencies.containsValue(beanInstance))||//BY_TYPEmatchesBeanName返回falsematchesBeanName(candidateName,descriptor.getDependencyName())){returncandidateName;}}returnnull;}resolvableDependencies中key-value存储的总结比较明确Injection在实际场景中确实用的比较少,但是了解过程还是可以让你获得一些相关的知识和过程,给自己和所有看的同学打气本文~!!微信公众号:CoderLi