Spring Bean实例的创建及构造器的挑选

作者:做猪呢,最重要的是开森啦 时间:2021-08-02 09:35:57 

一、举个栗子


public class BeanServiceImpl implements BeanService {
}

@Configuration
public class ConfigurationBean {

@Bean
   public BeanService beanService() {
       BeanServiceImpl beanService = new BeanServiceImpl();
       System.out.println("beanService: " + beanService);
       return beanService;
   }

@Bean
   //@Bean 如果不知道name,默认bean的name为方法名,下面等同于@Bean("beanService1")
   public BeanService beanService1() {
       BeanServiceImpl beanService1 = new BeanServiceImpl();
       System.out.println("beanService1: " + beanService1);
       return beanService1;
   }
}

@Component
public class SetterBean {

private BeanService bs;

public SetterBean(BeanService beanService) {
       bs = beanService;
       System.out.println("有参构造:" + bs);
   }
}

二、创建实例的方式

  • 通过Supplier的回调方法去创建

  • 通过工厂方法去创建通过

  • 反射构造器去创建

绝大部分是通过反射构造器去创建,详情源码见AbstractAutowireCapableBeanFactory.doCreateBean中的createBeanInstance方法

三、反射构造器结论现象

3.1 没有有参构造器

如果没有有参构造器,默认使用无参的构造方法反射创建实例,详情见createBeanInstance – instantiateBean方法


protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
... ...
// No special handling: simply use no-arg constructor.
return instantiateBean(beanName, mbd);
}

3.2 有唯一的有参构造器

如果有唯一有参构造器,并且参数能在Spring容器里找到,则通过该有参构造器反射创建
    详情见createBeanInstance – autowireConstructor方法


protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
... ...
// Candidate constructors for autowiring?
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
... ...
}

如果参数不能在Spring容器中找到,就会报NoUniqueBeanDefinitionException异常

3.3 有多个有参构造器,不指定构造器

有多个有参构造器,Spring在创建Bean实例时,就不知道用哪个构造器去创建,就会报如下异常:
  BeanInstantiationException: Failed to instantiate [XXX]: No default constructor found;


@Component
public class SetterBean {

private BeanService bs;

public SetterBean(BeanService beanService) {
       bs = beanService;
       System.out.println("有参构造:" + bs);
   }

//@Autowired
   public SetterBean(BeanService beanService, BeanService beanService1) {
       bs = beanService;
       System.out.println("有参构造:" + bs + "--------" + beanService1);
   }
}

3.4 有多个有参构造器,指定有参构造

可以通过@Autowired来指定有参构造来创建实例

像3.2 中,把@Autowired注释打开,就会使用该有参构造创建实例,启动就不会报异常,

四、createBeanInstance功能简介

这个方法主要是挑选构造器,然后创建实例的

  • 依次判断使用哪种方式创建实例

  • 有参构造是否已经解析过,解析过就从缓存中拿解析过的构造器去创建

  • 没有解析缓存过,则通过后置处理器去获取构造器,参数如果需要注入,则autowireConstructor去注入参数,然后创建实例

  • 都不符合的话就拿默认的无参构造器去创建实例

来源:https://blog.csdn.net/weixin_43901882/article/details/115803878

标签:java,Spring,Bean,实例创建,构造器
0
投稿

猜你喜欢

  • C#实现支付宝沙箱支付的项目实践

    2021-07-29 17:18:18
  • Android仿微信长按录制视频并播放功能

    2023-02-16 23:26:33
  • Java深入学习图形用户界面GUI之创建窗体

    2022-11-17 02:40:36
  • 浅谈SpringMVC+Spring3+Hibernate4开发环境搭建

    2023-08-06 13:49:19
  • Unity实现游戏卡牌滚动效果

    2023-09-20 10:54:23
  • Java事件处理步骤讲解

    2023-10-14 11:49:57
  • 深入理解Java并发编程之LinkedBlockingQueue队列

    2022-10-02 06:35:22
  • Java实现带GUI的气泡诗词效果

    2022-09-12 18:04:48
  • Java使用自定义注解实现为事件源绑定事件监听器操作示例

    2023-06-21 01:17:55
  • Springmvc ResponseBody响应json数据实现过程

    2022-06-12 15:22:30
  • WinForm判断关闭事件来源于用户点击右上角“关闭”按钮的方法

    2021-05-28 13:00:43
  • SpringBoot借助spring.factories文件跨模块实例化Bean

    2021-12-01 18:22:41
  • Mybatis Plus中的流式查询案例

    2023-08-18 16:35:13
  • MyBatis中映射文件的使用案例代码

    2021-09-02 23:55:41
  • Qt串口通信开发之QSerialPort模块简单使用方法与实例

    2023-03-23 03:25:45
  • java在网页上面抓取邮件地址的方法

    2023-10-01 19:18:21
  • C#使用HttpClient的正确方式你了解吗

    2023-07-04 12:12:40
  • C#基于基姆拉尔森算法计算指定日期是星期几的方法

    2022-04-28 09:31:25
  • 各种格式的编码解码工具类分享(hex解码 base64编码)

    2021-11-17 07:04:51
  • 浅谈AnDroidDraw+DroidDraw实现Android程序UI设计的分析说明

    2023-09-28 20:41:51
  • asp之家 软件编程 m.aspxhome.com