@Bean 标注的方法如何创建对象呢?
参考文章:blog.csdn.net/qq_35971258...
下边只讲一下 @Bean 注解标注的方法,是如何去进行创建 bean,以及流程是怎样的,如果需要看源码具体执行流程,可以查看上边
参考文章
Spring 的 @Bean 标注的方法会被创建成 Bean,这个创建的过程在源码中是怎么执行的呢?
java
@Configuration
public class MyConfiguration {
@Bean
public Blue blue() {
System.out.println("创建 Blue 对象");
return new Blue();
}
}
当使用上述代码时,在 Spring 中扫描到 MyConfiguration 类时,会发现 MyConfiguration 的 BeanDefinition 包含了 FactoryMethod,也就是 Spring 为带有 @Bean 注解的方法创建了一个 FactoryMethod,这个 FactoryMethod 也就是 blue()
方法,最后通过执行 FactoryMethodblue()
就可以创建出 Blue 对象,再将 Blue 对象交给 Spring 进行管理,最后创建的 Blue 对象的 beanName 就是 @Bean 标注的方法名
总结一下: @Bean 标注的方法会是一个 FactoryMethod,最后通过执行这个 FactoryMethod 来创建 Bean 对象,beanName 为方法名 {beanName: blud, }
Spring 的 @Bean 标注的方法的参数如何注入的呢?
java
@Configuration
public class MyConfiguration {
@Bean
public Blue blue(White white) {
System.out.println("创建 Blue 对象");
System.out.println("获取了 White 对象:" + white);
return new Blue();
}
@Bean
public White white() {
White white = new White();
System.out.println("创建的 White 对象:" + white);
return white;
}
/**
* 输出:
* 创建的 White 对象:com.zqy.springbean.SpringBean.beans.White@32c726ee
* 创建 Blue 对象
* 获取了 White 对象:com.zqy.springbean.SpringBean.beans.White@32c726ee
*/
}
参数注入流程为:
- 对上边的 @Bean 方法来说,如果方法存在参数,会先根据参数名到 Spring 容器中取出对应的 bean,即先根据
white
取出对应的 bean - 如果根据
white
没有取到对应的 bean,就会根据对象的类型去取,如果 Spring 容器中,White
类型的 Bean 只有 1 个,就会取出来进行赋值 - 但是如果 Spring 容器中
White
类型的 Bean 有多个时,Spring 内部就会进行决策判断,通过决策判断出来需要使用哪个 Bean 进行赋值,如果没有决策成功,Spring 就会报错Parameter 0 of method blue in com.zqy.springbean.SpringBean.MyConfiguration required a single bean, but 2 were found:
,即 Spring 根据类型找到了多个 Bean,但是并不知道使用哪一个!
这个决策过程为:
- 如果 Spring 找到多个同类型的 Bean,会查看是否有 Bean 标注了 @Primary 注解,如果有,就使用该 Bean 进行赋值
- 如果没有标注 @Primary,则会判断这几个 Bean 是否实现了 @Comparator 排序接口,如果有,就使用该 Bean
- 如果都没有找到,再根据入参名称和 beanName 进行比较,如果相同就使用该 Bean,否则报错
下面我们对这几种情况进行代码演示:
-
根据 beanName 找到入参
会发现根据 beanName 成功找到 bean 对象,赋值给 blue() 方法的入参
java@Configuration public class MyConfiguration { @Bean public Blue blue(White white1) { System.out.println("获取了 White 对象:" + white1); return new Blue(); } @Bean public White white1() { White white = new White(); System.out.println("创建的 White1 对象:" + white); return white; } /** * 输出: 创建的 White1 对象:com.zqy.springbean.SpringBean.beans.White@2c07545f 获取了 White 对象:com.zqy.springbean.SpringBean.beans.White@2c07545f */ }
-
如果有多个同类型的 bean,根据 @Primary 找到 Bean 进行赋值
可以发现,入参注入的 bean 对象为携带了 @Primary 注解的 bean
java@Configuration public class MyConfiguration { @Bean public Blue blue(White white) { System.out.println("获取了 White 对象:" + white); return new Blue(); } @Bean @Primary public White white1() { White white = new White(); System.out.println("创建的 White1 对象,携带 @Primary 注解:" + white); return white; } @Bean public White white2() { White white = new White(); System.out.println("创建的 White2 对象:" + white); return white; } /** * 输出: 创建的 White1 对象,携带 @Primary 注解:com.zqy.springbean.SpringBean.beans.White@2c4d1ac 获取了 White 对象:com.zqy.springbean.SpringBean.beans.White@2c4d1ac 创建的 White2 对象:com.zqy.springbean.SpringBean.beans.White@7f0d96f2 */ }
-
有多个同类型的 bean,根据
入参名
和beanName
比较进行赋值可以发现,入参名为
white1
,White 类型的 bean 有两个,beanName 分别为white1
和white2
,根据比较,入参使用white1
的 beanjava@Configuration public class MyConfiguration { @Bean public Blue blue(White white1) { System.out.println("获取了 White 对象:" + white1); return new Blue(); } @Bean public White white1() { White white = new White(); System.out.println("创建的 White1 对象:" + white); return white; } @Bean public White white2() { White white = new White(); System.out.println("创建的 White2 对象:" + white); return white; } /** * 输出: 创建的 White1 对象:com.zqy.springbean.SpringBean.beans.White@2c07545f 获取了 White 对象:com.zqy.springbean.SpringBean.beans.White@2c07545f 创建的 White2 对象:com.zqy.springbean.SpringBean.beans.White@e57b96d */ }