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

一、举个栗子

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去注入参数,然后创建实例
  • 都不符合的话就拿默认的无参构造器去创建实例

到此这篇关于Spring Bean实例的创建及构造器的挑选的文章就介绍到这了,更多相关Bean实例创建及构造器挑选内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Spring如何使用xml创建bean对象

    一.导入JAR包 二.配置applicationContext.xml的spring核心配置 三. public static void main(String[] args) { //1.使用 ApplicationContext 接口,就是在获取 spring 容器 ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); //2.根据 bean 的 id 获取对象 IAccountService

  • Java基础之Bean的创建、定位和使用

    一.前言 Bean是一个由Spring IoC容器实例化.组装和管理的对象.在 Spring 中,类的实例化.依赖的实例化.依赖的传入都交由 Spring Bean 容器控制,而不是用new方式实例化对象.通过非构造函数方法传入依赖等常规方式.这样可以减少垃圾回收对大量实例的回收工作. 在举例中使用到了三个类AAA,BBB和CCC.其中AAA和BBB是平等的两个类,可以相互调用.CCC是以BBB为构造参数的类. 二.自动装配Bean 2.1 注册Bean 为所有想要创建Bean的类添加@Comp

  • 创建动态代理对象bean,并动态注入到spring容器中的操作

    使用过Mybatis的同学,应该都知道,我们只需要编写mybatis对应的接口和mapper XML文件即可,并不需要手动编写mapper接口的实现.这里mybatis就用到了JDK动态代理,并且将生成的接口代理对象动态注入到Spring容器中. 这里涉及到几个问题.也许有同学会有疑问,我们直接编写好类,加入@Component等注解不是可以注入了吗?或者在配置类(@Configuration)中直接声明该Bean类型不也可以注入吗? 但具体到mybatis,这里我们用的是接口.由于spring

  • Spring-Bean创建对象的步骤方式详解

    1.通过无参构造函数创建(默认) 2.通过有参构造创建 1.constructor 的index赋值 <bean id="user" class="com.c.pojo.user"> <constructor-arg index= 0 value=" "> </bean> 2.constructor 的 type 方式: <bean id="user" class="com.

  • Spring创建Bean的过程Debug的详细流程

    Spring流程Debug 1.1 Spring测试环境搭建 Spring模块概览,绿色是模块,Spring中八大模块,黑色表示该模块包含的jar包(组件).例如我们想要用IOC容器,也就是绿色的CoreContainer,我们需要导入Beans,Core,Context,SpEL(spring-expression)四个包. Test:测试相关 Core Container:IOC容器 AOP:面向切面编程 Aspects:切面 Instrumenttation:跟JDK关联,一般不用 Mes

  • Spring实战之使用静态工厂方法创建Bean操作示例

    本文实例讲述了Spring实战之使用静态工厂方法创建Bean操作.分享给大家供大家参考,具体如下: 一 配置 <?xml version="1.0" encoding="GBK"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" x

  • Spring框架花式创建Bean的n种方法(小结)

    常用的从容器中获取bean实例使用这样的方式: @Test public void test() { Persion p = (Persion) ioc.getBean("p1"); System.out.println(p); } 常用的在容器中配置组件使用这样的方式: <bean id="p1" class="com.gql.bean.Persion"> <property name="name" val

  • Spring创建bean对象三种方式代码实例

    一.使用无参构造方法创建 二.使用静态工厂创建 三.使用实例工厂创建 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们.

  • Spring框架通过工厂创建Bean的三种方式实现

    工厂模式 Spring中bean的创建,默认是框架利用反射new出来的bean实例.有时候也会有一些复杂的情况. 假设有一个飞机,属性如下,现在需要造很多同型号的飞机,那么唯一需要改变的属性只有DriverName(机长姓名),此时可以使用工厂模式帮我们创建对象,有一个专门帮我们创建对象的类帮我们创建对象,这个类就叫工厂. public class AirPlane { private String DriverName;// 机长姓名 private String AirPlaneName;/

  • Spring实战之调用实例工厂方法创建Bean操作示例

    本文实例讲述了Spring实战之调用实例工厂方法创建Bean操作.分享给大家供大家参考,具体如下: 一 配置 <?xml version="1.0" encoding="GBK"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" x

随机推荐