Spring6当中获取Bean的四种方式小结

作者:

文章目录
  • 比如:《杀死一只是更鸟》中提到的 对应我们:我们努力升本,考研,每天都在努力学习,但是某天突然想到万一没有考上的话,那现在的努力又有什么意义呢? 答案:在《杀死一只是更鸟》里有这样一段话: 勇敢是,当你还未开始,你就知道自己会输,可你依然要去做,而且无论如何都要把它坚持到底,你很少能赢,但有时也会。努力的这个过程本身就是有意义,能够获得理想的结果当然很好,但如果失败了也没关系。因为你的勇敢,从未辜负你的青春,而黎明的光亮,总有一刻,会照亮穿梭于黑暗之中的自己。 况且,你还不一定会输呢。 Spring 为Bean 的获取提供了多种方式,通常包括4种方式。(也就是说在Spring中为Bean对象的创建准备了多种方案,目的是:更加灵活) 第一种:通过构造方法实例化,获取 Bean对象 第二种:通过简单工厂模式实例化,获取Bean对象 第三种:通过factory-bean 属性,获取Bean对象 第四种:通过对FactoryBean 接口的实例化,获取Bean对象
  • 在Spring 当中 为什么要将 Date 作为复杂类型进行注入呢? 原因是,在Spring 如果将 Date 作为简单类型进行注入的话,需要特定的时间格式,才能注入成功。 准备工作:定义一个 Bean 类,同时其中含有一个 Date 类型的属性值。 package com.rainbowsea.Bean.myDate; import java.util.Date; public class Vip { private Date birth; public Vip(Date birth) { this.birth = birth; } public Vip() { } public Date getBirth() { return birth; } public void setBirth(Date birth) { this.birth = birth; } @Override public String toString() { return “Vip{” + “birth=” + birth + ‘}’; } } 演示如下: 警告: Exception encountered during context initialization – cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘vipBean’ defined in class path resource [spring2.xml]: Failed to convert property value of type ‘java.lang.String’ to required type ‘java.util.Date’ for property ‘birth’; Cannot convert value of type ‘java.lang.String’ to required type ‘java.util.Date’ for property ‘birth’: no matching editors or conversion strategy found 对应Spring当中的 Date 作为简单类型的注入,需要用如下它美国的格式时间格式,才能被识别为 Date 类型。特殊格式如下: Mon Apr 29 20:03:58 CST 2024 虽然转化成功了,但是这个格式,对于我们国人来说,不太友好,而且也不好记忆。 所以为了将Date 类型转化为我们国人友好的类型的格式,我们就需要将 Date 定义为 复杂类型 进行 ref 注入。但是怎样将 Date 作为复杂类型注入的同时又可以转换为我们需要的格式呢。——这就需要用到上面我们所学习的通过 FactoryBean接口 获取 Bean 对象了。其实呢,上面第二种方式,第三种方式,第四种方式都是可以实现的。但是第四种方式比较简化,我们这里就用第四种方式来解决。这个问题。 第一步: 定义一个含有 Date 类型的类,就还是使用上面哪个 Vip 类吧 第二步: 创建一个用于生产我们所需要的格式的 Date的工厂 同时该工厂又实现了 implements FactoryBean 接口。告诉Spring框架,调用其中的哪个对象当中的哪个方法,获取到我们所需要的 Date 对象。 package com.rainbowsea.Bean.myDate; import org.springframework.beans.factory.FactoryBean; import java.text.SimpleDateFormat; import java.util.Date; /** * Date 工厂模式 * DateFactoryBean 这个工厂Bean 协助我们Spring 创建这个普通的Bean;Date */ public class DateFactor implements FactoryBean<Date> { // 这个 String字符串类型,作为我们Date类型,进行一个转换 private String strDate; public DateFactor() { } public DateFactor(String strDate) { this.strDate = strDate; } public String getStrDate() { return strDate; } public void setStrDate(String strDate) { this.strDate = strDate; } @Override public Date getObject() throws Exception { // 通过 SimpleDateFormat 来自定义我们的 Date 的日期时间类型的格式 SimpleDateFormat simpleDateFormat = new SimpleDateFormat(“yyyy-MM-dd”); // 通过在 spring.xml 对DateFactor类当中的 String strDate 属性进行赋值 Date date = simpleDateFormat.parse(this.strDate); // 将字符串类型转换为 Date 日期时间类型 return date; // 转换后返回 Date 类型,进行一个赋值操作 } @Override public Class<?> getObjectType() { return null; } @Override public boolean isSingleton() { return true; // 单例 false 多例 } } 上述代码的核心代码片段讲解: // 这个 String字符串类型,作为我们Date类型,进行一个转换 private String strDate; public Date getObject() throws Exception { // 通过 SimpleDateFormat 来自定义我们的 Date 的日期时间类型的格式 SimpleDateFormat simpleDateFormat = new SimpleDateFormat(“yyyy-MM-dd”); // 通过在 spring.xml 对DateFactor类当中的 String strDate 属性进行赋值 Date date = simpleDateFormat.parse(this.strDate); // 将字符串类型转换为 Date 日期时间类型 return date; // 转换后返回 Date 类型,进行一个赋值操作 } 通过定义一个Date 类型的工厂类 生产出,我们需要的格式的 Date 类型。 第三步: 为我们这个 工厂类(生产我们所需的Date日期类型格式),配置到 Spring 当中去,并让 Spirng 框架返回一个我们需要的 Date类型的 Bean 对象,同时作为复杂类型,赋值到 Vip 这个类当中的 birth 属性的值。 <?xml version=”1.0″ encoding=”UTF-8″?> <beans xmlns=”http://www.springframework.org/schema/beans” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:schemaLocation=”http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd”> <!– 指明通过DateFactor 获取到一个我们所需要的格式的 Date 类型–> <bean id=”myDateBean” class=”com.rainbowsea.Bean.myDate.DateFactor”> <property name=”strDate” value=”1980-01-01″></property> </bean> <!– 获取到之后,作为复杂类型,赋值给 Vip 当中的 Date birth 属性值–> <bean id=”vipBean” class=”com.rainbowsea.Bean.myDate.Vip”> <property name=”birth” ref=”myDateBean”></property> </bean> </beans> 第四步: 运行程序测试 核心要素就是:通过一个(这里时生产我们所需格式的 Date 类型的)工厂类实现 FactoryBean接口,被称为“工厂Bean”。“工厂Bean(通过工厂上的方法返回一个对应的 Bean(这里时 Date ) 对象)”是一种特殊的Bean。获取到对应 Date 后,再作为 复杂类型作为其他类上的属性的值存在。
  • 第一种通过构造方法获取 Bean:简单的说:就是通过在spring的配置文件中,进行一个配置,从而调取其中 Bean 的构成方法,获取到 对应的Bean对象。 第二种方式:通过简单工厂模式获取 Bean;注意时工厂类中生产对应的Bean对象是静态方法()。同时其中的 Bean 本质上还是程序员自己 new()出来的。 通过简单工厂模式,你需要在Spring当中配置文件种告诉 Spring框架,调用哪个类当中的哪个方法可以获取到这个你要的 Bean; factory-method 指明方法()对应方法的小写。 factory-method= 属性我们这里指定的是 UserFactory 工厂类当中静态方法,也就是告诉Spring 框架,调用方法可以获取到你要的Bean 对象。 第三种方式:通过 factory-bean 属性获取 Bean;使用 factory-bean 属性获取 Bean,本质上是,使用23种设计模式当中的工厂方法模式。(注意 其中的工厂类当中的生产对应 Bean的方法是实例方法(不是静态方法),其中的 Bean 本质上还是程序员自己 new()出来的 ) 这里我们需要用到以下,两个标签属性,才能让spirng 准确的调用哪个类当中的哪个对象的方法,获取,返回给我们自己想要的 Bean 对象,这里是User 这个 bean对象。 factory-bean 指明哪个对象factory-method当中的哪个方法;可以获取到你想要的 bean 第四种方式:通过 FactoryBean 接口 获取 Bean;简单的说:就是对第三种方式的一种简化,通过让对应的工厂类是实现该接口implements FactoryBean ,Spring就知道该调用哪个对象,中的哪个方法,获取到你要的 Bean 对象了 。从到到达了某种程度上的简化。 该方式的核心就在于:通过一个特殊的Bean(工厂Bean当中的方法)<该工厂实现了 FactoryBean 接口 >,来返回一个普通的Bean 对象。 BeanFactroy 和 FactroyBean 的区别 将Date 作为复杂类型进行注入(可以自定义 Date 时间类型的格式); 对应Spring当中的 Date 作为简单类型的注入,需要用如下它美国的格式时间格式,才能被识别为 Date 类型。 核心要素就是:通过一个(这里时生产我们所需格式的 Date 类型的)工厂类实现 FactoryBean接口,被称为“工厂Bean”。“工厂Bean(通过工厂上的方法返回一个对应的 Bean(这里时 Date ) 对象)”是一种特殊的Bean。获取到对应 Date 后,再作为 复杂类型作为其他类上的属性的值存在。
  • 以上就是Spring6当中获取Bean的四种方式小结的详细内容,更多关于Spring6获取Bean的资料请关注风君子博客其它相关文章! 您可能感兴趣的文章: Spring6.x对调度和异步执行的注解支持示例详解 浅谈Spring6中的反射机制 Spring6整合JUnit的详细步骤 将应用程序进行Spring6迁移的最佳使用方式
  • 目录
    • 每博一文案
    • 1. Spring6 当中 获取 Bean 的四种方式
      • 1.1 第一种方式:通过构造方法获取 Bean
      • 1.2 第二种方式:通过简单工厂模式获取 Bean
      • 1.3 第三种方式:通过 factory-bean 属性获取 Bean
      • 1.4 第四种方式:通过 FactoryBean 接口 获取 Bean
      • 1.5 BeanFactroy 和 FactroyBean 的区别
    • 2. 将Date 作为复杂类型进行注入(可以自定义 Date 时间类型的格式)
      • 3. 总结
        • 4. 最后:

          比如:《杀死一只是更鸟》中提到的
          对应我们:我们努力升本,考研,每天都在努力学习,但是某天突然想到万一没有考上的话,那现在的努力又有什么意义呢?
          答案:在《杀死一只是更鸟》里有这样一段话:
          勇敢是,当你还未开始,你就知道自己会输,可你依然要去做,而且无论如何都要把它坚持到底,你很少能赢,但有时也会。努力的这个过程本身就是有意义,能够获得理想的结果当然很好,但如果失败了也没关系。因为你的勇敢,从未辜负你的青春,而黎明的光亮,总有一刻,会照亮穿梭于黑暗之中的自己。
          况且,你还不一定会输呢。
          

          Spring 为Bean 的获取提供了多种方式,通常包括4种方式。(也就是说在Spring中为Bean对象的创建准备了多种方案,目的是:更加灵活)

          • 第一种:通过构造方法实例化,获取 Bean对象
          • 第二种:通过简单工厂模式实例化,获取Bean对象
          • 第三种:通过factory-bean 属性,获取Bean对象
          • 第四种:通过对FactoryBean 接口的实例化,获取Bean对象

          简单的说:就是通过在spring的配置文件中,进行一个配置,从而调取其中 Bean 的构成方法,获取到 对应的Bean对象。

          准备工作:通过 maven 导入 Spring6的框包

          <?xml version="1.0" encoding="UTF-8"?>
          <project xmlns="http://maven.apache.org/POM/4.0.0"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
              <modelVersion>4.0.0</modelVersion>
          
              <groupId>com.rainbowsea</groupId>
              <artifactId>spring6-005-bean-instantiation-blog</artifactId>
              <version>1.0-SNAPSHOT</version>
              <packaging>jar</packaging>
          
              <properties>
                  <maven.compiler.source>17</maven.compiler.source>
                  <maven.compiler.target>17</maven.compiler.target>
              </properties>
          
          
              <dependencies>
                  <dependency>
                      <groupId>org.springframework</groupId>
                      <artifactId>spring-context</artifactId>
                      <version>6.0.11</version>
                  </dependency>
          
          
                  <!-- junit4 -->
                  <dependency>
                      <groupId>junit</groupId>
                      <artifactId>junit</artifactId>
                      <version>4.13.2</version>
                      <scope>test</scope>
                  </dependency>
              </dependencies>
          
          
          </project>
          

          这里我们创建一个User 的类,方便我们进行一个,测试。为了测试效果,更加明显,这里这个User类就定义成一个空的类吧

          在这里插入图片描述

          配置相关的 spring.xml 配置文件信息内容,告知 Spirng 框架,帮我们进行一个管理。

          外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

          <?xml version="1.0" encoding="UTF-8"?>
          <beans xmlns="http://www.springframework.org/schema/beans"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
          
              <!--   第一种: 通过构造方法获取 Bean -->
              <bean id="user" class="com.rainbowsea.Bean.User"></bean>
          </beans>
          

          运行测试,看是否能够,获取到我们想要的这个 User 类对象。

          外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

          
          import com.rainbowsea.Bean.User;
          import org.springframework.context.ApplicationContext;
          import org.springframework.context.support.ClassPathXmlApplicationContext;
          
          public class Test {
          
              @org.junit.Test
              public void test() {
                  ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring6.xml");
                  User user = applicationContext.getBean("user", User.class);
                  System.out.println(user);
              }
          }
          
          

          从上述结果,我们通过构造方法,获取到了 Bean 对象。

          第一步: 定义一个Bean,还是使用 User 对象

          在这里插入图片描述

          外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 第二步: 编写简单工厂模式当中的工厂类。

          注意: 这里的 User 对象,本质上,还是我们程序员自己给 new 出来的,并不是 Spring 帮我们弄的。

          在这里插入图片描述

          /**
           * 特点:它是简单工厂模式(静态工厂模式),是静态的一个方法
           *
           */
          public class UserFactory {
              public static User get() {
          
                  // 本质上,还是我们自己程序员自己 new 出来的
                  return new User();
              }
          }
          

          第三步:在Spring配置文件中指定创建该Bean的方法(使用factory-method属性指定)

          通过简单工厂模式,你需要在Spring当中配置文件种告诉 Spring框架,调用哪个类当中的哪个方法可以获取到这个你要的 Bean; factory-method 指明方法()对应方法的小写。

          factory-method= 属性我们这里指定的是 UserFactory 工厂类当中静态方法,也就是告诉Spring 框架,调用方法可以获取到你要的Bean 对象。

          在这里插入图片描述

          <?xml version="1.0" encoding="UTF-8"?>
          <beans xmlns="http://www.springframework.org/schema/beans"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
          
             
              <!--   第二种: 通过简单工厂模式,你需要在Spring当中配置文件种告诉 Spring框架,调用哪个类当中的哪个方法可以获取到这个
          你要的 Bean; factory-method 指明方法()对应方法的小写 -->
              <!--    factory-method= 属性指定的时工厂类当中静态方法,也就是告诉Spring 框架,调用方法可以获取到你要的
              Bean-->
              <bean id="userFactory" class="com.rainbowsea.Bean.UserFactory" factory-method="get"></bean>
          </beans>
          

          第四步: 编写测试程序

          在这里插入图片描述

          在这里插入图片描述

          通过: 这样一个配置,就让我们告知了 Spring 框架,你调用那个类当中的哪里方法,就可以获取到我们想要的Bean 对象。

          使用 factory-bean 属性获取 Bean,本质上是,使用23种设计模式当中的工厂方法模式(注意,这里没有错,不了解的,可能会认为是,我写错了,并没有写错这里)。

          **第一步:**定义一个 Bean 对象。这里我们还是使用 User 这里类,进行试验。

          在这里插入图片描述

          第二步: 既然是工厂方法模式,自然是少不了,工厂了。需要注意这里是工厂方法模式,与静态工厂模式不同,这个生产 Bena 对象的方法,不是静态方法,而是实例化方法 。这也导致了,我们在接下来后续的 spring.xml 配置文件上与第二种 方式有所差异的。注意其中的差异,所使用的标签,不要弄错了。

          在这里插入图片描述

          package com.rainbowsea.Bean;
          
          /**
           * 特点:它是简单工厂模式(静态工厂模式),是静态的一个方法
           *
           */
          public class UserFactory {
          
              // 工厂方法模式中的具体工厂角色中的方法是:实例方法
              public User get() {
          
                  // 相同点是和静态工厂方法模式是一样的:都是我们自己程序员 new 的。
                  // 然后交给 Spring框架管理
                  return new User();
              }
          }
          
          

          **第三步:**在Spring配置文件中指定factory-bean以及factory-method

          上面我们说到,工厂方法模式与静态方法模式,不同点,上是工厂方法模式生产Bean 对象的方法,并不是一个 static() 方法 ,所以,使用的标签属性就有所不同了。

          这里我们需要用到以下,两个标签属性,才能让spirng 准确的调用哪个类当中的哪个对象的方法,获取,返回给我们自己想要的 Bean 对象,这里是User 这个 bean对象。

          • factory-bean 指明哪个对象
          • factory-method当中的哪个方法;可以获取到你想要的 bean

          简单的说:告诉Spring 通过哪个对象,当中的哪个方法,可以获取到我想要的 Bean 对象

          在这里插入图片描述

          <?xml version="1.0" encoding="UTF-8"?>
          <beans xmlns="http://www.springframework.org/schema/beans"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
          
          
              <!--    第三种:通过Spring提供的实例化方式,通过工厂方法模式,通过
               factory-bean 指明哪个对象+factory-method当中的哪个方法;可以获取到你想要的 bean-->
              <!--    简单的说:就是告诉Spring框架,调用哪个对象中的哪个方法,就可以获取到你想要的 Bean了-->
          
          
              <bean id="userFactory" class="com.rainbowsea.Bean.UserFactory"> </bean>
              <!--    以下的配置很关键: factory-bean:告诉Spring框架调用哪个对象; factory-method 告诉Spring框架
              调用哪个方法,可以获取到你要的Bean-->
              <bean id="userBean" factory-bean="userFactory" factory-method="get"></bean>
          </beans>
          

          第四步: 测试运行结果。

          在这里插入图片描述

          import com.rainbowsea.Bean.User;
          import org.springframework.context.ApplicationContext;
          import org.springframework.context.support.ClassPathXmlApplicationContext;
          
          public class Test {
          
              @org.junit.Test
              public void test() {
                  ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring6.xml");
                  User user = applicationContext.getBean("userBean", User.class);
                  System.out.println(user);
              }
          }
          
          

          以上的第三种方式中,factory-bean的属性值是我们自定义的,factory-method的属性值也是我们自己定义的。

          在Spring中,当你编写的类直接实现FactoryBean接口之后,factory-bean不需要指定了,factory-method也不需要指定了。

          factory-bean会自动指向实现FactoryBean接口的类,factory-method会自动指向getObject()方法。

          在这里插入图片描述

          package org.springframework.beans.factory;
          
          import org.springframework.lang.Nullable;
          
          public interface FactoryBean<T> {
          
          	String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
          
          
          	@Nullable
          	T getObject() throws Exception;
          
          
          	@Nullable
          	Class<?> getObjectType();
          
              
          	default boolean isSingleton() {
          		return true;
          	}
          
          }
          
          

          第四种方式:简单的说:就是对第三种方式的一种简化,通过让对应的工厂类是实现该接口implements FactoryBean ,Spring就知道该调用哪个对象,中的哪个方法,获取到你要的 Bean 对象了 。从到到达了某种程度上的简化。

          第一步: 定义一个Bean

          这里我们还是使用 User 这里类,进行试验。

          在这里插入图片描述

          第二步: 编写一个(工厂模式当中的)工厂类实现 FactoryBean接口

          下面,我们来了解一下,FactoryBean接口下的这个三个方法的作用是干啥的

          // 返回我们所需要的 Bean 对象
          T getObject() throws Exception;
          
          

          例如:注意一点:这里还是需要我们自己 new() 出对应所需要的 Bean 对象,而不是 Spirng 弄出来的

          @Override
              public User getObject() throws Exception {
                  return new User();  // 还是需要我们程序员自己 new() 出来
              }
          
           /**
               * 这个方法在接口中有默认实现
               * 默认返回 true,表示单例的
               * 如果想多例的化,直接讲这个修改为: return false 即可。
               * @return
               */
          default boolean isSingleton() {
          		return true;
          	}
          
          
          例如:
              @Override
              public boolean isSingleton() {
                  return true;  // 单例
              }
          

          这里我们定义了一个 UserFactory 产生 User 的对象的工厂类,同时实现implements FactoryBean 该接口。

          在这里插入图片描述

          package com.rainbowsea.Bean;
          
          import org.springframework.beans.factory.FactoryBean;
          
          /**
           * 特点:它是简单工厂模式(静态工厂模式),是静态的一个方法
           *
           */
          public class UserFactory implements FactoryBean<User> {
          
          
              @Override
              public User getObject() throws Exception {
                  // 本质上还是我们程序员自己 new ()出来的,并不是 Spring 弄出来
                  return new User();
              }
          
              // 这个方法可以不用管它。
              @Override
              public Class<?> getObjectType() {
                  return null;
              }
          
              @Override
              public boolean isSingleton() {
                  return true;  // 单例
                  // false 多例
              }
          
          }
          
          

          **第三步:**在Spring配置文件中配置FactoryBean

          由于我们这个public class UserFactory implements FactoryBean 生产 User 的工厂实现了 FactoryBean 接口,Spring 已经是知道,我们需要调用的是哪个对象当中的哪个方法,从而获取对应的 user Bean对象了。所以对应其中的 spinrg.xml 只需要简单的配置一下,即可。

          如下:

          在这里插入图片描述

          将方式的核心就在于:通过一个特殊的Bean(工厂Bean当中的方法)<该工厂实现了 FactoryBean 接口 >,来返回一个普通的Bean 对象。

          <?xml version="1.0" encoding="UTF-8"?>
          <beans xmlns="http://www.springframework.org/schema/beans"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
          
          
              <!--   Spring框架中:获取Bean的第四种方式:通过 FactoryBean 接口来实现指明 -->
              <!--    这种方式实际上就是第三种方式的简化-->
              <!--    由于你编写的类实现了FactoryBean接口,那么这个类就是一个特殊的类,不需要你再手动指定: factory-bean;
              factory-method 哪个对象,哪个方法了,你实现了 FactoryBean 接口,Spring框架就已经知道了,不需要再特殊指明了-->
              <!--    剩下指明是哪个特殊的类就可以了-->
              <!--    通过一个特殊的Bean,工厂Bean,来返回一个普通的Bean person对象-->
              <bean id="userFactory" class="com.rainbowsea.Bean.UserFactory"></bean>
          </beans>
          

          在这里插入图片描述

          第四步: 运行程序测试。

          在这里插入图片描述

          package com.rainbowsea.test;
          
          import com.rainbowsea.Bean.User;
          import org.springframework.context.ApplicationContext;
          import org.springframework.context.support.ClassPathXmlApplicationContext;
          
          public class Test {
          
              @org.junit.Test
              public void test() {
                  ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring6.xml");
                  User user = applicationContext.getBean("userFactory", User.class);
                  System.out.println(user);
              }
          }
          
          

          FactoryBean在Spring中是一个接口。被称为“工厂Bean”。“工厂Bean(通过工厂上的方法返回一个 对应的 Bean 对象)”是一种特殊的Bean。所有的“工厂Bean”都是用来协助Spring框架来创建其他Bean对象的。

          BeanFactory

          Spring IoC容器的顶级对象,BeanFactory被翻译为“Bean工厂”,在Spring的IoC容器中,“Bean工厂”负责创建Bean对象。 BeanFactory是工厂。

          在这里插入图片描述

          FactoryBean

          FactoryBean:它是一个Bean,是一个能够辅助Spring实例化其它Bean对象的一个Bean。
          在Spring中,Bean可以分为两类:

          第一类:普通Bean第二类:工厂Bean(记住:工厂Bean也是一种Bean,只不过这种Bean,比较特殊工厂Bean(通过工厂上的方法返回一个 对应的 Bean 对象),从而到达辅助Spring实例化其它Bean对象的效果。)

          在Spring 当中 为什么要将 Date 作为复杂类型进行注入呢?

          原因是,在Spring 如果将 Date 作为简单类型进行注入的话,需要特定的时间格式,才能注入成功。

          准备工作:定义一个 Bean 类,同时其中含有一个 Date 类型的属性值。

          package com.rainbowsea.Bean.myDate;
          
          import java.util.Date;
          
          public class Vip {
          
              private Date birth;
          
              public Vip(Date birth) {
                  this.birth = birth;
              }
          
              public Vip() {
              }
          
              public Date getBirth() {
                  return birth;
              }
          
              public void setBirth(Date birth) {
                  this.birth = birth;
              }
          
              @Override
              public String toString() {
                  return "Vip{" +
                          "birth=" + birth +
                          '}';
              }
          }
          
          

          演示如下:

          在这里插入图片描述

          警告: Exception encountered during context initialization – cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘vipBean’ defined in class path resource [spring2.xml]: Failed to convert property value of type ‘java.lang.String’ to required type ‘java.util.Date’ for property ‘birth’; Cannot convert value of type ‘java.lang.String’ to required type ‘java.util.Date’ for property ‘birth’: no matching editors or conversion strategy found

          对应Spring当中的 Date 作为简单类型的注入,需要用如下它美国的格式时间格式,才能被识别为 Date 类型。特殊格式如下:

          Mon Apr 29 20:03:58 CST 2024
          

          在这里插入图片描述

          虽然转化成功了,但是这个格式,对于我们国人来说,不太友好,而且也不好记忆。

          所以为了将Date 类型转化为我们国人友好的类型的格式,我们就需要将 Date 定义为 复杂类型

          进行 ref 注入。但是怎样将 Date 作为复杂类型注入的同时又可以转换为我们需要的格式呢。——这就需要用到上面我们所学习的通过 FactoryBean接口 获取 Bean 对象了。其实呢,上面第二种方式,第三种方式,第四种方式都是可以实现的。但是第四种方式比较简化,我们这里就用第四种方式来解决。这个问题。

          第一步: 定义一个含有 Date 类型的类,就还是使用上面哪个 Vip 类吧

          在这里插入图片描述

          第二步: 创建一个用于生产我们所需要的格式的 Date的工厂 同时该工厂又实现了 implements FactoryBean 接口。告诉Spring框架,调用其中的哪个对象当中的哪个方法,获取到我们所需要的 Date 对象。

          在这里插入图片描述

          package com.rainbowsea.Bean.myDate;
          
          
          import org.springframework.beans.factory.FactoryBean;
          
          import java.text.SimpleDateFormat;
          import java.util.Date;
          
          /**
           * Date 工厂模式
           * DateFactoryBean 这个工厂Bean 协助我们Spring 创建这个普通的Bean;Date
           */
          public class DateFactor implements FactoryBean<Date> {
          
              // 这个 String字符串类型,作为我们Date类型,进行一个转换
              private String strDate;
          
              public DateFactor() {
              }
          
              public DateFactor(String strDate) {
                  this.strDate = strDate;
              }
          
              public String getStrDate() {
                  return strDate;
              }
          
              public void setStrDate(String strDate) {
                  this.strDate = strDate;
              }
          
              @Override
              public Date getObject() throws Exception {
                  // 通过 SimpleDateFormat 来自定义我们的 Date 的日期时间类型的格式
                  SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
                  // 通过在 spring.xml 对DateFactor类当中的  String strDate 属性进行赋值
                  Date date = simpleDateFormat.parse(this.strDate); // 将字符串类型转换为 Date 日期时间类型
                  return date;  // 转换后返回 Date 类型,进行一个赋值操作
              }
          
              @Override
              public Class<?> getObjectType() {
                  return null;
              }
          
              @Override
              public boolean isSingleton() {
                  return true;  // 单例 false 多例
              }
          }
          
          

          上述代码的核心代码片段讲解:

          
              // 这个 String字符串类型,作为我们Date类型,进行一个转换
              private String strDate;
          
          
              public Date getObject() throws Exception {
                  // 通过 SimpleDateFormat 来自定义我们的 Date 的日期时间类型的格式
                  SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
                  // 通过在 spring.xml 对DateFactor类当中的  String strDate 属性进行赋值
                  Date date = simpleDateFormat.parse(this.strDate); // 将字符串类型转换为 Date 日期时间类型
                  return date;  // 转换后返回 Date 类型,进行一个赋值操作
              }
          

          在这里插入图片描述

          通过定义一个Date 类型的工厂类 生产出,我们需要的格式的 Date 类型。

          第三步: 为我们这个 工厂类(生产我们所需的Date日期类型格式),配置到 Spring 当中去,并让 Spirng 框架返回一个我们需要的 Date类型的 Bean 对象,同时作为复杂类型,赋值到 Vip 这个类当中的 birth 属性的值。

          在这里插入图片描述

          在这里插入图片描述

          <?xml version="1.0" encoding="UTF-8"?>
          <beans xmlns="http://www.springframework.org/schema/beans"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
          
          <!--    指明通过DateFactor 获取到一个我们所需要的格式的 Date 类型-->
              <bean id="myDateBean" class="com.rainbowsea.Bean.myDate.DateFactor">
                  <property name="strDate" value="1980-01-01"></property>
              </bean>
          <!--    获取到之后,作为复杂类型,赋值给 Vip 当中的 Date birth 属性值-->
              <bean id="vipBean" class="com.rainbowsea.Bean.myDate.Vip">
                 <property name="birth" ref="myDateBean"></property>
              </bean>
          </beans>
          

          第四步: 运行程序测试

          在这里插入图片描述

          核心要素就是:通过一个(这里时生产我们所需格式的 Date 类型的)工厂类实现 FactoryBean接口,被称为“工厂Bean”。“工厂Bean(通过工厂上的方法返回一个对应的 Bean(这里时 Date ) 对象)”是一种特殊的Bean。获取到对应 Date 后,再作为 复杂类型作为其他类上的属性的值存在。

          第一种通过构造方法获取 Bean:简单的说:就是通过在spring的配置文件中,进行一个配置,从而调取其中 Bean 的构成方法,获取到 对应的Bean对象。

          第二种方式:通过简单工厂模式获取 Bean;注意时工厂类中生产对应的Bean对象是静态方法()。同时其中的 Bean 本质上还是程序员自己 new()出来的。

          通过简单工厂模式,你需要在Spring当中配置文件种告诉 Spring框架,调用哪个类当中的哪个方法可以获取到这个你要的 Bean; factory-method 指明方法()对应方法的小写。

          factory-method= 属性我们这里指定的是 UserFactory 工厂类当中静态方法,也就是告诉Spring 框架,调用方法可以获取到你要的Bean 对象。

          第三种方式:通过 factory-bean 属性获取 Bean;使用 factory-bean 属性获取 Bean,本质上是,使用23种设计模式当中的工厂方法模式。(注意 其中的工厂类当中的生产对应 Bean的方法是实例方法(不是静态方法),其中的 Bean 本质上还是程序员自己 new()出来的 )

          这里我们需要用到以下,两个标签属性,才能让spirng 准确的调用哪个类当中的哪个对象的方法,获取,返回给我们自己想要的 Bean 对象,这里是User 这个 bean对象。 factory-bean 指明哪个对象factory-method当中的哪个方法;可以获取到你想要的 bean

          第四种方式:通过 FactoryBean 接口 获取 Bean;简单的说:就是对第三种方式的一种简化,通过让对应的工厂类是实现该接口implements FactoryBean ,Spring就知道该调用哪个对象,中的哪个方法,获取到你要的 Bean 对象了 。从到到达了某种程度上的简化。

          该方式的核心就在于:通过一个特殊的Bean(工厂Bean当中的方法)<该工厂实现了 FactoryBean 接口 >,来返回一个普通的Bean 对象。

          BeanFactroy 和 FactroyBean 的区别

          将Date 作为复杂类型进行注入(可以自定义 Date 时间类型的格式);

          对应Spring当中的 Date 作为简单类型的注入,需要用如下它美国的格式时间格式,才能被识别为 Date 类型。

          核心要素就是:通过一个(这里时生产我们所需格式的 Date 类型的)工厂类实现 FactoryBean接口,被称为“工厂Bean”。“工厂Bean(通过工厂上的方法返回一个对应的 Bean(这里时 Date ) 对象)”是一种特殊的Bean。获取到对应 Date 后,再作为 复杂类型作为其他类上的属性的值存在。

          以上就是Spring6当中获取Bean的四种方式小结的详细内容,更多关于Spring6获取Bean的资料请关注风君子博客其它相关文章!

          您可能感兴趣的文章:

          • Spring6.x对调度和异步执行的注解支持示例详解
          • 浅谈Spring6中的反射机制
          • Spring6整合JUnit的详细步骤
          • 将应用程序进行Spring6迁移的最佳使用方式

          站内搜索