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 有多个有参构造器,指定有参构造
可以通过
像3.2 中,把@Autowired注释打开,就会使用该有参构造创建实例,启动就不会报异常,@Autowired
来指定有参构造来创建实例
四、createBeanInstance功能简介
这个方法主要是挑选构造器,然后创建实例的
依次判断使用哪种方式创建实例
有参构造是否已经解析过,解析过就从缓存中拿解析过的构造器去创建
没有解析缓存过,则通过后置处理器去获取构造器,参数如果需要注入,则autowireConstructor去注入参数,然后创建实例
都不符合的话就拿默认的无参构造器去创建实例
来源:https://blog.csdn.net/weixin_43901882/article/details/115803878
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
解决springcloud中Feign导入依赖为unknow的情况
Java Web Fragment在项目中使用方法详解
![](https://img.aspxhome.com/file/2023/5/64775_0s.png)
如何将javaweb项目部署到linux下
java中超过long范围的超大整数相加算法详解(面试高频)
![](https://img.aspxhome.com/file/2023/0/61850_0s.png)
JavaFx实现拼图游戏
![](https://img.aspxhome.com/file/2023/4/69714_0s.jpg)
Java实现答答租车系统
![](https://img.aspxhome.com/file/2023/9/61579_0s.jpg)
深入讲解我们说的CAS自旋锁到底是什么
深入理解ThreadLocal工作原理及使用示例
![](https://img.aspxhome.com/file/2023/6/62066_0s.png)
详解Spring Boot 定制HTTP消息转换器
![](https://img.aspxhome.com/file/2023/3/59853_0s.png)
android线程消息机制之Handler详解
![](https://img.aspxhome.com/file/2023/1/85961_0s.jpg)
JAVA实现KMP算法理论和示例代码
Netty启动流程注册多路复用源码解析
![](https://img.aspxhome.com/file/2023/0/65750_0s.png)
java中对list分页并显示数据到页面实例代码
Java的Hibernate框架中Criteria查询使用的实例讲解
教你使用Java获取当前时间戳的详细代码
Java实现图片拼接
IDEA SpringBoot项目配置热更新的步骤详解(无需每次手动重启服务器)
![](https://img.aspxhome.com/file/2023/9/59659_0s.jpg)
详解如何在SpringBoot项目中使用统一返回结果
![](https://img.aspxhome.com/file/2023/4/58714_0s.png)
SSH框架网上商城项目第10战之搭建商品类基本模块
![](https://img.aspxhome.com/file/2023/6/59006_0s.png)
elasticsearch集群发现zendiscovery的Ping机制分析
![](https://img.aspxhome.com/file/2023/2/60572_0s.jpg)