• Spring中@Bean标注的方法是如何创建对象呢?


    @Bean 标注的方法如何创建对象呢?

    参考文章:https://blog.csdn.net/qq_35971258/article/details/128241353

    下边只讲一下 @Bean 注解标注的方法,是如何去进行创建 bean,以及流程是怎样的,如果需要看源码具体执行流程,可以查看上边参考文章

    Spring 的 @Bean 标注的方法会被创建成 Bean,这个创建的过程在源码中是怎么执行的呢?

    @Configuration
    public class MyConfiguration {
    
        @Bean
        public Blue blue() {
            System.out.println("创建 Blue 对象");
            return new Blue();
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    当使用上述代码时,在 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 标注的方法的参数如何注入的呢?

    @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
         */
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    参数注入流程为:

    1. 对上边的 @Bean 方法来说,如果方法存在参数,会先根据参数名到 Spring 容器中取出对应的 bean,即先根据 white 取出对应的 bean
    2. 如果根据 white 没有取到对应的 bean,就会根据对象的类型去取,如果 Spring 容器中,White 类型的 Bean 只有 1 个,就会取出来进行赋值
    3. 但是如果 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,但是并不知道使用哪一个!

    这个决策过程为:

    1. 如果 Spring 找到多个同类型的 Bean,会查看是否有 Bean 标注了 @Primary 注解,如果有,就使用该 Bean 进行赋值
    2. 如果没有标注 @Primary,则会判断这几个 Bean 是否实现了 @Comparator 排序接口,如果有,就使用该 Bean
    3. 如果都没有找到,再根据入参名称和 beanName 进行比较,如果相同就使用该 Bean,否则报错

    下面我们对这几种情况进行代码演示:

    1. 根据 beanName 找到入参

      会发现根据 beanName 成功找到 bean 对象,赋值给 blue() 方法的入参

      @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
           */
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
    2. 如果有多个同类型的 bean,根据 @Primary 找到 Bean 进行赋值

      可以发现,入参注入的 bean 对象为携带了 @Primary 注解的 bean

      @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
           */
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
    3. 有多个同类型的 bean,根据入参名beanName比较进行赋值

      可以发现,入参名为 white1 ,White 类型的 bean 有两个,beanName 分别为 white1white2,根据比较,入参使用 white1 的 bean

      @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
           */
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26

  • 相关阅读:
    python循环时循环体一会多一会少,这个思路值得参考
    java版本+工程项目管理系统源码+项目模块功能清单+spring cloud +spring boot
    动态规划34(Leetcode337打家劫舍3)
    跟运维学 Linux - 02
    软件著作权可以有几个作者?其保护作用是哪些?
    聊聊wireshark的进阶使用功能
    IDEA .iml文件及.idea文件夹详解
    2009-2018年各省涉农贷款数据(wind)
    了解IP地址的基本概念和修改步骤
    《算法系列》之回溯
  • 原文地址:https://blog.csdn.net/qq_45260619/article/details/134244387