龙岗区建设局网站,wordpress转载视频,内蒙古头条新闻发布信息,推广普通话的重要性1.什么是依赖注入
控制反转#xff08;IoC#xff09;和依赖注入#xff08;DI#xff09;是Spring框架的核心设计思想#xff0c;具体来说DI其实是对IoC的一种实现。抛开八股#xff0c;依赖注入给使用者最直观的感受是Spring会自动给类#xff08;bean#x…1.什么是依赖注入
控制反转IoC和依赖注入DI是Spring框架的核心设计思想具体来说DI其实是对IoC的一种实现。抛开八股依赖注入给使用者最直观的感受是Spring会自动给类bean的属性赋值不需要我们手动地调用setter方法。所以Spring不仅会自动地创建bean并且还会给bean里面的属性赋值。给属性赋值的过程我们称之为依赖注入。
1.1 构造器注入和setter方法注入
我们先来看看在Java中如何给一个类的实例设置属性
public class SimpleBased {private String property1;private int property2;public SimpleBased() {}public SimpleBased(String property1, int property2) {this.property1 property1;this.property2 property2;}public String getProperty1() {return property1;}public void setProperty1(String property1) {this.property1 property1;}public int getProperty2() {return property2;}public void setProperty2(int property2) {this.property2 property2;}Overridepublic String toString() {return SimpleBased{ property1 property1 \ , property2 property2 };}
}public class IOCTest {Testpublic void simpleTest(){// 通过构造器注入SimpleBased simpleConstructorBased new SimpleBased(property1, 2);System.out.println(simpleConstructorBased);// 通过setter注入SimpleBased simpleSetterBased new SimpleBased();simpleSetterBased.setProperty1(property1.1);simpleSetterBased.setProperty2(3);System.out.println(simpleSetterBased);}
} 可以看到我们设置一个对象的属性通过两种途径一种是创建对象时通过构造方法指定属性值另一种是在对象创建好后调用setter方法。
Spring框架的依赖注入DI本质上也是通过这两种方式实现我们通常这两种方式为构造器注入和setter方法注入。
我们以XML配置为例来看看Spring是怎么实现这两种方式的属性注入
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd!--构造器注入--bean classcom.source.ioc.SimpleBased namesimpleConstructorBasedconstructor-arg valueconstructor nameproperty1 typejava.lang.String/constructor-arg value1 nameproperty2 typeint//bean!--setter注入--bean classcom.source.ioc.SimpleBased namesimpleSetterBasedproperty valuesetter nameproperty1/property value1 nameproperty2//bean
/beansTest
public void simpleXmlTest(){ClassPathXmlApplicationContext ac new ClassPathXmlApplicationContext(spring-di.xml);SimpleBased simpleSetterBased ac.getBean(simpleSetterBased, SimpleBased.class);System.out.println(simpleSetterBased);SimpleBased simpleConstructorBased ac.getBean(simpleConstructorBased, SimpleBased.class);System.out.println(simpleConstructorBased);
} 运行结果如下 在配置xml文件时无论bean的属性是什么类型标签中的value属性的类型均是StringSpring会自动帮我们做类型转换。 如果当前bean依赖其他bean时该怎么配置呢
constructor-arg标签和property标签都支持ref属性用于将bean的指定属性的值设置为对容器管理的另一个bean的引用。我们可以通过一个简单的例子来看看首先我们定义好相关的bean
public class SpringIOC {public static class SpringIOC1 {private String property;public SpringIOC1() {this.property i am SpringIOC1;}Overridepublic String toString() {return SpringIOC1{ property1 property \ };}}public static class SpringIOC2 {private String property;public SpringIOC2() {this.property i am SpringIOC2;}Overridepublic String toString() {return SpringIOC2{ property1 property \ };}}public static class SpringIOC3 {private String property;private SpringIOC1 springIOC1;private SpringIOC2 springIOC2;public SpringIOC3(SpringIOC1 springIOC1) {this.property i am SpringIOC3;this.springIOC1 springIOC1;}public void setSpringIOC2(SpringIOC2 springIOC2) {this.springIOC2 springIOC2;}Overridepublic String toString() {return SpringIOC3{ property property \ , springIOC1 springIOC1 , springIOC2 springIOC2 };}}
} 接着我们在XML文件中配置这些bean
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdbean classcom.source.ioc.SpringIOC.SpringIOC1 namespringIOC1/bean classcom.source.ioc.SpringIOC.SpringIOC2 namespringIOC2/bean idspringIOC3 classcom.source.ioc.SpringIOC.SpringIOC3constructor-arg namespringIOC1 refspringIOC1/property namespringIOC2 refspringIOC2//bean
/beans 最后编写测试方法
Test
public void simpleXmlBeanTest(){ClassPathXmlApplicationContext ac new ClassPathXmlApplicationContext(ioc/spring-di-bean.xml);SpringIOC.SpringIOC3 springIOC3 ac.getBean(springIOC3, SpringIOC.SpringIOC3.class);System.out.println(springIOC3);
} 控制台打印结果如下 可以看到通过ref属性成功将XML配置文件中的bean注入到目标bean当中。
1.2 自动注入
从上面的demo中通过配置XML文件Spring能很好地帮助我们完成依赖注入。
但是这又产生了另一个问题如果bean依赖很多其他bean那么配置文件就会非常复杂为此Spring提供了自动注入的功能。通过配置bean标签的autowire属性来设置自动注入的模式一共有四种模式
1.no默认值。不启用自动装配。bean必须引用由ref定义的元素。虽然配置要多一点但是这样可以让系统结构和bean之间的关系更加清晰。2.byName通过属性的名字的方式查找bean依赖的对象并为其注入。比如说某个bean的autowire属性为byName并且有个属性名为a有个setA方法那么IoC容器会在配置文件中查找id/name的值包含a的bean然后使用setter方法模式为其注入。注意这里的自动setter相比前面讲的手动setter注入有限制即setXXX方法的XXX一定要对应一个容器中实例的name才行否则不会注入。3.byType通过属性的类型查找bean依赖的对象并为其注入。比如说某个bean的autowire属性为byType并且有个属性名为a有个setA方法这个属性a的类型为com.A那么IoC容器会在配置文件中查找class为com.A的bean然后使用setter方法模式为其注入。注意这里的自动setter注入相比手动setter配注入有限制即setXXX方法的XXX一定是属性名才行第一个字母可以改变大小写。如果容器有多个同类型的bean那么抛出异常expected single matching bean but found x: xxx。4.constructor同byType一样也是通过类型查找依赖对象。与byType的区别在于它不是使用setter方法注入而是使用构造器注入。如果容器有多个同类型的bean并且不能找到最合适的依赖那么同样会抛出异常expected single matching bean but found x: xxx。 如果使用自动注入模式我们将SpringIOC3去掉有参构造增加无参构造
public static class SpringIOC3 {private String property;private SpringIOC1 springIOC1;private SpringIOC2 springIOC2;public SpringIOC3() {}public void setSpringIOC2(SpringIOC2 springIOC2) {this.springIOC2 springIOC2;}Overridepublic String toString() {return SpringIOC3{ property property \ , springIOC1 springIOC1 , springIOC2 springIOC2 };}
} XML配置如下
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdbean classcom.source.ioc.SpringIOC.SpringIOC1 namespringIOC1/bean classcom.source.ioc.SpringIOC.SpringIOC2 namespringIOC2/bean idspringIOC3 classcom.source.ioc.SpringIOC.SpringIOC3 autowirebyType//beans 最后运行结果如下 因为我们将autowire属性设置为byTypeSpringIOC3虽然有springIOC1和springIOC2两个属性但是只有springIOC2有set方法因此最后只有springIOC2自动注入成功。 [!IMPORTANT] 由于byType和byName均是通过set方法实现自动注入的因此需要一个空参的构造方法来实例化bean。 这里顺带提一嘴在最开始接触Spring框架时觉着自动注入功能很高级如果从源码的角度来看Spring在部分功能的实现确实挺复杂的但是仅通过实现逻辑来看其实并没有那么复杂我们简单来分析一下
在前面的博客中我们有分析过Spring会根据XML文件和注解来帮我们实例化bean并将这些bean保存到Spring容器中。Spring 容器本质是一个大的Mapkey为bean的namevalue为bean的实例对象。
对于byType和byNameSpring只需要根据name或者类型去查这个大Map取出bean的实例通过反射调用setter方法完成依赖注入
而对于constructor则首先通过反射得到构造器的参数类型然后根据类型查大Map取出bean实例最后通过反射调用构造方法实例化bean并完成依赖注入。
上面只是简单的介绍整个自动注入的流程Spring实际的实现肯定比这复杂得多。
2.基于XML配置的DI源码解析
想要了解依赖注入的源码实现一定是绕不开Spring初始化bean的流程这部分内容在之前的博客中已经详细讲述了为保证前后文的连贯性这里就简单过一下大致流程。
依赖注入的实现主要在于两点保存XML的依赖配置信息、取出依赖配置信息完成依赖注入。
那么Spring会见XML的bean的依赖配置信息放在哪里呢答beanDefinition。我们先来看看Spring初始化bean的过程中beanDefinition是怎么随着XML配置的变化而变化的。
我们先来看看方法入口
2.1 加载beanDefinition
我们先来看看加载beanDefintion的粗略过程 从两个角度来看看beanDefinition保存的信息手动指定依赖注入信息和自动注入。
2.1.1 手动注入-setter 我们先来看看手动指定依赖注入信息
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdbean classcom.source.ioc.SpringIOC.SpringIOC1 namespringIOC1/bean classcom.source.ioc.SpringIOC.SpringIOC2 namespringIOC2/bean idspringIOC3 classcom.source.ioc.SpringIOC.SpringIOC3property namespringIOC2 refspringIOC2//bean
/beans 这时springIOC3的beanDefinition如下 2.1.2 手动注入-构造器
我们再看看通过constructor-arg标签通过构造器注入
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdbean classcom.source.ioc.SpringIOC.SpringIOC1 namespringIOC1/bean classcom.source.ioc.SpringIOC.SpringIOC2 namespringIOC2/bean idspringIOC3 classcom.source.ioc.SpringIOC.SpringIOC3constructor-arg namespringIOC1 refspringIOC1//bean
/beans 这时springIOC3的beanDefinition如下
2.1.3 自动注入
我们把依赖注入改为自动注入
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdbean classcom.source.ioc.SpringIOC.SpringIOC1 namespringIOC1/bean classcom.source.ioc.SpringIOC.SpringIOC2 namespringIOC2/bean idspringIOC3 classcom.source.ioc.SpringIOC.SpringIOC3 autowirebyName/
/beans 继续打断点看看自动注入模式下的springIOC3的beanDefinition 自动注入虽然有四种模式但是反应在beanDefinition上面只会影响到autowireMode一个属性autowireMode通过一个整型来区分不同的自动注入模式。
现在我们知道了依赖注入的配置信息主要是通过beanDefinition的propertyValues属性、autowireMode属性和constructorArgumentValues属性完成的这三个属性也是完成依赖注入的依据。
1.2节中我们提到过自动注入有四种模式这四种模式和autowireMode的值对应如下
no - autowireMode0
byName - autowireMode1
byType - autowireMode2
constructor - autowireMode3 由于自动注入没有明确指定需要注入哪些属性Spring只能从设置的自动注入模式来推测我们来看看四种自动注入模式下beanDefinition的propertyValues和constructorArgumentValues属性值
public static class SpringIOC3 {private String property;private SpringIOC1 springIOC1;private SpringIOC2 springIOC2;public SpringIOC3() {}public SpringIOC3(SpringIOC1 springIOC1) {this.springIOC1 springIOC1;}public void setSpringIOC2(SpringIOC2 springIOC2) {this.springIOC2 springIOC2;}Overridepublic String toString() {return SpringIOC3{ property property \ , springIOC1 springIOC1 , springIOC2 springIOC2 }; }}2.2 依赖注入源码分析
前面我们讨论了Spring是如何保存XML中关于依赖注入的配置信息接下来我们来看看Spring是如何完成依赖注入的。
我们先来分析一下依赖注入的时机根据前文的介绍得知依赖注入无论是手动注入还是自动注入只会通过两个途径构造器注入或者setter方法注入。结合之前Spring初始化bean的博客来看依赖注入会发生在bean的实例化阶段和属性填充阶段。
bean的实例化本质是通过得到Class对象然后利用反射调用构造器完成实例化因此当我们设置构造器注入时会在这个阶段通过有参构造完成依赖注入。
属性填充则会调用对应字段的setter方法完成依赖注入。
前面的博客中我们已经详细分析了Spring初始化bean的全过程这里就不再赘述为了保证行文的流畅性简单概括一下bean的初始化过程。
我们从refresh方法来看 2.2.1 手动注入-构造器
我们重新调整一下Demo
public class SpringIOC {public static class SpringIOC1 {private String property;public SpringIOC1() {this.property i am SpringIOC1;}Overridepublic String toString() {return SpringIOC1{ property1 property \ };}}public static class SpringIOC2 {private String property;public SpringIOC2() {this.property i am SpringIOC2;}Overridepublic String toString() {return SpringIOC2{ property1 property \ };}}public static class SpringIOC3 {private String property;private SpringIOC1 springIOC1;private SpringIOC2 springIOC2;public SpringIOC3() {}public SpringIOC3(SpringIOC1 springIOC1) {this.springIOC1 springIOC1;}public void setSpringIOC2(SpringIOC2 springIOC2) {this.springIOC2 springIOC2;}Overridepublic String toString() {return SpringIOC3{ property property \ , springIOC1 springIOC1 , springIOC2 springIOC2 };}}
} 重新调整一下XML配置文件
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdbean classcom.source.ioc.SpringIOC.SpringIOC1 namespringIOC1/bean classcom.source.ioc.SpringIOC.SpringIOC2 namespringIOC2/bean idspringIOC3 classcom.source.ioc.SpringIOC.SpringIOC3constructor-arg namespringIOC1 refspringIOC1/property namespringIOC2 refspringIOC2//bean
/beans 可以看到SpringIOC3有两个构造器空参构造和包含SpringIOC1的构造我们继续进到AbstractAutowireCapableBeanFactory的createBeanInstance方法关于这个方法的具体讲解在之前的博客Spring源码学习三finishBeanFactoryInitialization-CSDN博客中有提到这里我们只聚焦于与依赖注入相关的关键部分
// AbstractAutowireCapableBeanFactory.java的第1200行到1204行
Constructor?[] ctors determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors ! null || mbd.getResolvedAutowireMode() AUTOWIRE_CONSTRUCTOR ||mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {return autowireConstructor(beanName, mbd, ctors, args);
} determineConstructorsFromBeanPostProcessors方法是通过Spring后处理器来获得被Autowire注解修饰的构造器这个方法只会在开启注解后才会生效如果使用XML配置则该方法返回为null。
在本小结给出的demo中会进入if判断来调用autowireConstructor方法我们来逐个分析一下这四个判断条件
ctors ! nullfalse因为没开启注解determineConstructorsFromBeanPostProcessors返回为nullmbd.getResolvedAutowireMode()false因为没开启自动注入beanDefinition的autowireMode的值为0AUTOWIRE_CONSTRUCTOR的值为3mbd.hasConstructorArgumentValues()true在2.1.2中有提到过使用了constructor-arg注解后beanDefinition的constructorArgumentValues属性不为空!ObjectUtils.isEmpty(args)false这是判断实例化bean时是否使用外部参数默认是不适用所以args是null。
if条件成立接着我们进入到AbstractAutowireCapableBeanFactory的autowireConstructor方法
protected BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd, Nullable Constructor?[] ctors, Nullable Object[] explicitArgs) {return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
} autowireConstructor方法里面会创建一个ConstructorResolver的对象然后再调用ConstructorResolver的autowireConstructor方法这里的this其实就是beanFactory的本身保存了所有bean的beanDefinition。
我们继续进到autowireConstructor的方法注意这里入参ctors和explicitArgs均为nullautowireConstructor方法较长且在之前的博客中有详细讲述我们这里只关注关键代码部分 我们结合本小节的demo看看Spring是怎么计算autowiring属性的值
chosenCtors ! nullfalse这里的chosenCtors 就是autowireConstructor的入参这里的入参值为nullmbd.getResolvedAutowireMode() AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTORfalse不使用自动注入时beanDefinition的autowireMode的值为0AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR的值为3。 [!NOTE] 这里的autowiring的其实是注解和xml配置两个方便综合考虑的结果。 再来看看resolveConstructorArguments方法该方法做了两件事计算构造函数最少参数数量属性minNrOfArgs和解析依赖的bean在进到resolveConstructorArguments方法之前先来回顾一下beanDefinition的constructorArgumentValues属性 可以看到constructorArgumentValues由indexedArgumentValues和genericArgumentValues两个属性构成当我们使用constructor-arg标签时可以设置index属性表示构造器的第几个入参可以看个简单的例子
bean idexampleBean classcom.example.ExampleClassconstructor-arg index0 valueFirst Argument/constructor-arg index1 valueSecond Argument/
/bean Spring会将设置了index属性的constructor-arg标签信息保存到indexedArgumentValues而没设置index属性的constructor-arg标签信息保存到genericArgumentValues属性当中。
在本小节的例子中没有设置index属性因此constructor-arg标签信息会被保存到genericArgumentValues属性中。
在了解了constructorArgumentValues的基本构成之后我们再来看看resolveConstructorArguments方法 constructorArgumentValues由indexedArgumentValues和genericArgumentValues两个属性构成minNrOfArgs则是这两个属性的size之和 关于Spring将beanName解析为对应的bean的方法resolveValueIfNecessary底层其实是通过beanFactory的getBean方法套娃了属于是完成的这里就不再详细展开 让我们重新回到autowireConstructor方法继续往下看 Spring对候选构造器的排序规则如下
访问权限修饰符越高的越靠前参数越多的越靠前
排序完成后会遍历这些候选构造器选出最合适的一个构造器这部分代码在之前的博客中已经讲解过了这里就不再赘述我们只看看minNrOfArgs的过滤作用 在本小节的demo中SpringIOC3虽然有空参构造但是minNrOfArgs的值为101空参构造就会被过滤掉。
在找到了合适的构造函数已经入参对应的解析值后就可以根据反射来创建实例对象了同时完成了依赖注入 让我们来小结一下构造器依赖注入的整个流程关键其实在于constructorArgumentValues属性
Spring读取XML文件将constructor-arg标签的配置信息解析到beanDefinition的constructorArgumentValues属性中Spring会根据constructorArgumentValues计算构造器最少参数数量minNrOfArgs根据minNrOfArgs来过滤构造器Spring会根据constructorArgumentValues将依赖关系解析成对应的bean这里特指依赖其他bean的情况根据2和3的结果得到了构造器和构造器参数对应的值通过反射创建对象完成了依赖注入
2.2.2 手动注入-setter
我们继续沿用2.2.1的demoSpring在实例化SpringIOC3的对象时通过构造器注入成功注入了SpringIOC1的依赖接下来我们继续来看看SpringIOC2是如何注入的。
前文有说过setter注入是在bean的属性填充阶段完成的也就是populateBean方法我们进入到populateBean方法来看看 Spring到这一步是已经完成了SpringIOC3的实例化因此要想完成setter注入需要需要干两件事将beanName解析为bean调用对应属性的set方法将依赖注入到实例bean中。 我们进入到applyPropertyValues方法里面看看关键的部分 我们继续进到setPropertyValues方法里面看看这个方法位于AbstractPropertyAccessor setPropertyValue方法调用链较多我们来看看最后属性注入的代码 2.2.3 自动注入
在1.2节中讲到了自动注入的四种方式在2.1.3节中又讲到了四种自动注入模式在beanDefinition中对应的autowireMode的值接下来我们来看看Spring是如何处理这四种模式的自动注入。
Demo
public static class SpringIOC3 {private String property;private SpringIOC1 springIOC1;private SpringIOC2 springIOC2;public SpringIOC3() {}public SpringIOC3(SpringIOC1 springIOC1) {this.springIOC1 springIOC1;}public void setSpringIOC2(SpringIOC2 springIOC2) {this.springIOC2 springIOC2;}Overridepublic String toString() {return SpringIOC3{ property property \ , springIOC1 springIOC1 , springIOC2 springIOC2 };}
}2.2.3.1 autowire“no” 创建bean实例的createBeanInstance方法 可以看到最后使用的无参构造来实例化SpringIOC3如果我们把Demo中的无参构造去掉会怎么样呢程序会报错 接着来看看属性填充部分的代码populateBean可以看到核心逻辑一个没走压根没触发属性填充 2.2.3.2 autowire“byName”
先来看看beanDefinition 再来看看实例化bean方法 其实和 autowire“no”一样最后也是采用无参构造实例化bean也就是说使用byName自动注入如果没有无参构造程序会报错。
这个其实也比较好理解因为byName的本质是通过set方法完成依赖注入而调用set方法的前提是能实例化bean没有无参构造就无法实例化bean。
关键来看看属性填充方法 继续进到autowireByName方法 什么是符合要求的属性名称让我们进到unsatisfiedNonSimpleProperties方法来看看 我们来逐行分析
PropertyValues pvs mbd.getPropertyValues(); 因为我们没有主动在xml中配置property标签因此beanDefinition的propertyValues属性是个空数组这里的pvs也是一个空数组。
PropertyDescriptor[] pds bw.getPropertyDescriptors(); 获得当前bean的属性描述符Spring会通过反射解析bean的结构并缓存符合要求的属性信息。简单来说这一步可以获得有setter方法或者getter方法的属性信息。
pd.getWriteMethod() ! null !isExcludedFromDependencyCheck(pd) !pvs.contains(pd.getName()) !BeanUtils.isSimpleProperty(pd.getPropertyType()) 这一步是从pds中筛选出哪些属性要完成属性填充
pd.getWriteMethod() ! null该属性有setter方法的
!isExcludedFromDependencyCheck(pd)该属性没有排除依赖检查之外也就是不能为null
!pvs.contains(pd.getName())xml中的property标签没有配置该属性
!BeanUtils.isSimpleProperty(pd.getPropertyType())该属性不是简单属性 unsatisfiedNonSimpleProperties其实完成了一个属性检查的工作它会筛选出类里面非简单类型的有setter方法的属性。
unsatisfiedNonSimpleProperties方法找到符合要求的属性名称后通过getBean方法找到/创建bean作为该属性对应的属性值最后完成属性注入。 [!IMPORTANT] 通过这里我们知道byName并不会对所有属性进行依赖注入它会有两步过滤首先过滤出有setter/getter方法的属性然后再过滤出里面有setter方法的非简单类型的属性。 2.2.3.3 autowire“byType”
先来看看beanDefinition 对应的进到autowireByType方法 可以看到byType和byName的大体流程一致这里一个有意思的点是byType会对Object类型的属性进行过滤而byName并没有。
这是因为byName通过beanName找到的bean是唯一的而byType通过类型找到的bean可能不唯一特别是对于Object类型几乎可以接收所有类型的bean子类的值可以赋值给父类。
2.2.3.4 autowire“constructor”
先来看看beanDefinition 通过构造器注入需要重点看看createBeanInstance方法 可以看到if判断为true所以接下来的流程和2.2.1类似这里就不再赘述需要注意的一点是