当前位置:首页 >> 智能终端演进 >> 【Spring】Spring之推断构造方法源码解析,酷派8900

【Spring】Spring之推断构造方法源码解析,酷派8900

cpugpu芯片开发光刻机 智能终端演进 2
文件名:【Spring】Spring之推断构造方法源码解析,酷派8900 【Spring】Spring之推断构造方法源码解析

Spring的Bean生命周期中,需要通过构造方法来实例化对象,如果构造方法由多个或者手动指定构造方法,该如何选择用来实例化Bean的构造方法呢。

构造方法选择

一个构造方法时:如果只有一个无参的构造方法,那么实例化就只能使用这个构造方法了。如果只有一个有参的构造方法,那么实例化时要分情况讨论:

使用AnnotationConfigApplicationContext,会使用这个构造方法进行实例化,那么Spring会根据构造方法的参数信息去寻找bean,然后传给构造方法。使用ClassPathXmlApplicationContext,表示使用XML的方式来使用bean,要么在XML中指定构造方法的参数值(手动指定),要么配置autowire=constructor让Spring自动去寻找bean做为构造方法参数值。

多个构造方法时:

如果开发者指定了想要使用的构造方法,那么就用这个构造方法 xml中的标签,这个标签表示构造方法参数,可以根据这个确定想要使用的构造方法的参数个数,从而确定想要使用的构造方法@Autowired注解写在构造方法上时,表示开发者指定该方法为构造方法,Spring通过byType+byName的方式去找到符合条件的Bean作为构造方法的参数值 如果开发者没有指定想要使用的构造方法,则看开发者有没有让Spring自动去选择构造方法 只能用在ClassPathXmlApplicationContext,在xml中指定某个bean的autowire为constructor@Autowired或@Autowired(required=true)只能有一个,否则会报错,可以有多个@Autowired(required=false) 如果开发者也没有让Spring自动去选择构造方法,则Spring利用无参构造方法,如果没有无参构造方法,则报错

总结:

默认情况,用无参构造方法,或者只有一个构造方法就用那一个程序员指定了构造方法入参值,通过getBean()或者BeanDefinition.getConstructorArgumentValues()指定,那就用所匹配的构造方法程序员想让Spring自动选择构造方法以及构造方法的入参值,autowire=“constructor”程序员通过@Autowired注解指定了某个构造方法,但是希望Spring自动找该构造方法的入参值 创建Bean源码

入口方法,org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {} AbstractAutowireCapableBeanFactory类中的createBeanInstance()方法会去创建一个Bean实例根据BeanDefinition加载类得到Class对象如果BeanDefinition绑定了一个Supplier,那就调用Supplier的get方法得到一个对象并直接返回如果BeanDefinition中存在factoryMethodName,那么就调用该工厂方法得到一个bean对象并返回如果BeanDefinition已经自动构造过了,那就调用autowireConstructor()自动构造一个对象调用SmartInstantiationAwareBeanPostProcessor的determineCandidateConstructors()方法得到哪些构造方法是可以用的如果存在可用的构造方法,或者当前BeanDefinition的autowired是AUTOWIRE_CONSTRUCTOR,或者BeanDefinition中指定了构造方法参数值,或者创建Bean的时候指定了构造方法参数值,那么就调用**autowireConstructor()**方法自动构造一个对象最后,如果不是上述情况,就根据无参的构造方法实例化一个对象 autowireConstructor()方法 先检查是否指定了具体的构造方法和构造方法参数值,或者在BeanDefinition中缓存了具体的构造方法或构造方法参数值,如果存在那么则直接使用该构造方法进行实例化如果没有确定的构造方法或构造方法参数值,那么 如果没有确定的构造方法,那么则找出类中所有的构造方法如果只有一个无参的构造方法,那么直接使用无参的构造方法进行实例化如果有多个可用的构造方法或者当前Bean需要自动通过构造方法注入根据所指定的构造方法参数值,确定所需要的最少的构造方法参数值的个数对所有的构造方法进行排序,参数个数多的在前面遍历每个构造方法如果不是调用getBean方法时所指定的构造方法参数值,那么则根据构造方法参数类型找值如果是调用getBean方法时所指定的构造方法参数值,就直接利用这些值如果根据当前构造方法找到了对应的构造方法参数值,那么这个构造方法就是可用的,但是不一定这个构造方法就是最佳的,所以这里会涉及到是否有多个构造方法匹配了同样的值,这个时候就会用值和构造方法类型进行匹配程度的打分,找到一个最匹配的 打分匹配

分越低优先级越高,找到的bean和构造方法参数类型匹配程度越高。 示例:假设bean的类型为A,A的父类是B,B的父类是C,同时A实现了接口D。如果构造方法的参数类型为A,那么完全匹配,得分为0如果构造方法的参数类型为B,那么得分为2如果构造方法的参数类型为C,那么得分为4如果构造方法的参数类型为D,那么得分为1

@Bean

Spring会把@Bean修饰的方法解析成BeanDefinition。

方法是否为static的:

如果方法不是static的,那么解析出来的BeanDefinition中: factoryBeanName为AppConfig所对应的beanName,比如"appConfig"factoryMethodName为对应的方法名,比如"aService"factoryClass为AppConfig.class 如果方法是static的,那么解析出来的BeanDefinition中: factoryBeanName为nullfactoryMethodName为对应的方法名,比如"aService"factoryClass也为AppConfig.class

方法重载时,需要解析同一个@Bean注解的多个方法:

@Beanpublic static AService aService(){return new AService();}@Beanpublic AService aService(BService bService){return new AService();}

虽然有两个@Bean,但是肯定只会生成一个aService的Bean,那么Spring在处理@Bean时,也只会生成一个aService的BeanDefinition,比如Spring先解析到第一个@Bean,会生成一个BeanDefinition,此时isFactoryMethodUnique为true,但是解析到第二个@Bean时,会判断出来beanDefinitionMap中已经存在一个aService的BeanDefinition了,那么会把之前的这个BeanDefinition的isFactoryMethodUnique修改为false,并且不会生成新的BeanDefinition了。并且后续在根据BeanDefinition创建Bean时,会根据isFactoryMethodUnique来操作,如果为true,那就表示当前BeanDefinition只对应了一个方法,那也就是只能用这个方法来创建Bean了,但是如果isFactoryMethodUnique为false,那就表示当前BeanDefition对应了多个方法,需要和推断构造方法的逻辑一样,去选择用哪个方法来创建Bean。

协助本站SEO优化一下,谢谢!
关键词不能为空
同类推荐
«    2025年12月    »
1234567
891011121314
15161718192021
22232425262728
293031
控制面板
您好,欢迎到访网站!
  查看权限
网站分类
搜索
最新留言
文章归档
网站收藏
友情链接