• (七)Bean的实例化方式



    Spring学习目录

    上一篇:(六)Spring之回顾工厂模式

    下一篇:(八)Bean的生命周期

    环境

    spring6里程碑版本的仓库
    依赖:spring context依赖、junit依赖、log4j2依赖
    log4j2.xml文件放到类路径下。

    Bean的实例化方式

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

    • 第一种:通过构造方法实例化
    • 第二种:通过简单工厂模式实例化
    • 第三种:通过工厂方法模式实例化
    • 第四种:通过FactoryBean接口实例化

    通过构造方法实例化

    之前一直使用的就是这种方式。默认情况下,会调用Bean的无参数构造方法。
    在Spring配置文件直接配置类的全路径,Spring会自动调用该类的无参数构造方法来实例化Bean。
    创建一个Bean:SpringBean1类:

    public class SpringBean1 {
        public SpringBean1() {
            System.out.println("Spring Bean1的无参构造方法执行");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    创建spring.xml配置:

    <bean id="springBean1" class="com.bean.instantiation.bean.SpringBean1"/>
    
    • 1

    测试程序:

        @Test
        public void testInstantiation1(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
            SpringBean1 springBean1 = applicationContext.getBean("springBean1", SpringBean1.class);
            System.out.println(springBean1);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    请添加图片描述

    通过简单工厂模式实例化

    简单工厂模式实例化就是,创建一个简单工厂类,提供一个静态方法,手动实例化Bean对象,可见这个Bean是我们自己new出来的。
    需要在Spring配置文件中告诉Spring框架,调用哪个类的哪个方法获取Bean。

    定义一个Bean:SpringBean2类

    public class SpringBean2 {
        public SpringBean2() {
            System.out.println("Spring Bean2的无参构造方法执行");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    定义工厂类角色:SpringBean2Factory

    /**
     * 简单工厂模式中的工厂类角色。
     */
    public class SpringBean2Factory {
        //简单工厂模式又叫做静态工厂方法模式,有一个静态方法。
        public static SpringBean2 get(){
            //可见这个对象最终创建的时候还是我们负责new的。
            return new SpringBean2();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    spring.xml配置:
    factory-method属性:配置哪个方法获取Bean。

    <bean id="springBean2" class="com.bean.instantiation.bean.SpringBean2Factory" factory-method="get"/>
    
    • 1

    测试程序:

        @Test
        public void testInstantiation2(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
            SpringBean2 springBean2 = applicationContext.getBean("springBean2", SpringBean2.class);
            System.out.println(springBean2);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    请添加图片描述

    通过工厂方法模式实例化

    工厂方法模式实例化就是,创建一个简单工厂类,只是这个方法不再是静态方法,而是实例方法,手动实例化Bean对象,可见这个Bean也是我们自己new出来的。
    因为是实例方法,需要在Spring配置文件中配置这个工厂的Bean,并告诉Spring框架,调用哪个类的哪个方法获取Bean。

    定义一个Bean:SpringBean3类

    /**
     * 具体产品角色
     */
    public class SpringBean3 {
        public SpringBean3() {
            System.out.println("Spring Bean3的无参构造方法执行");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    工厂角色:SpringBean3Factory类

    /**
     * 具体工厂角色
     */
    public class SpringBean3Factory {
        //工厂方法模式里的方法是实例方法
        public SpringBean3 get(){
            //可见,创建对象还是我们直接创建的
            return new SpringBean3();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    spring.xml配置:
    通过factory-bean + factory-method共同完成
    因为是实例方法,需要实例化对象,所以工厂方法也需要Spring管理,需要配置bean

    • factory-method属性:配置哪个方法获取Bean。
    • factory-bean属性:指定哪个对象创建bean
    	<bean id="factory" class="com.bean.instantiation.bean.SpringBean3Factory"/>
    
        <bean id="springBean3" factory-bean="factory" factory-method="get"/>
    
    • 1
    • 2
    • 3

    测试程序:

        @Test
        public void testInstantiation3(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
            SpringBean3 springBean3 = applicationContext.getBean("springBean3", SpringBean3.class);
            System.out.println(springBean3);
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    请添加图片描述

    通过FactoryBean接口实例化

    前三种方式中,factory-bean是我们自定义的,factory-method也是我们自己定义的。
    在Spring中,当你编写的类直接实现FactoryBean接口之后,factory-bean不需要指定了,factory-method也不需要指定了。
    factory-bean会自动指向实现FactoryBean接口的类,factory-method会自动指向getObject()方法。
    第四种方案实际是第三种方案的简化

    定义一个Bean:SpringBean4类

    public class SpringBean4 {
        public SpringBean4() {
            System.out.println("Spring Bean4的无参构造方法执行");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    定义一个工厂:SpringBean4FactoryBean,实现FactoryBean接口
    这个工厂也是一个Bean,只不过这个Bean比较特殊,叫做工厂Bean
    通过这个工厂Bean可以获取普通的Bean
    FactoryBean接口有三个方法,分别是:

    • getObject():抽象方法,在这个方法创建Bean,并返回。
    • getObjectType():抽象方法,在这个方法编写返回Bean的类型,是一个Class类型。
    • isSingleton():默认方法,它会告诉Spring,创建Bean是否是单例的,默认为true是单例的,如果不想Bean为单例,则可以覆盖此方法,并返回false就可以。
    public interface FactoryBean<T> {
        String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
    
        @Nullable
        T getObject() throws Exception;
    
        @Nullable
        Class<?> getObjectType();
    
        default boolean isSingleton() {
            return true;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    SpringBean4FactoryBean:

    public class SpringBean4FactoryBean implements FactoryBean<SpringBean4> {
        /*
           在这个方法创建Bean
         */
        @Override
        public SpringBean4 getObject() throws Exception {
            //最终也是程序员自己new的
            return new SpringBean4();
        }
    
        @Override
        public Class<?> getObjectType() {
            return null;
        }
        /*
            在源码中有一个默认方法,它会告诉Spring,创建Bean是否是单例的,如果不想单例,覆盖该方法并返回false就可以
            这里就不在操作了,默认调用接口的默认方法
         */
        @Override
        public boolean isSingleton() {
            return FactoryBean.super.isSingleton();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    spring.xml配置:

    <bean id="springBean4" class="com.bean.instantiation.bean.SpringBean4FactoryBean"/>
    
    • 1

    测试程序:

        @Test
        public void testInstantiation4(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
            SpringBean4 springBean4 = applicationContext.getBean("springBean4", SpringBean4.class);
            System.out.println(springBean4);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    请添加图片描述

    BeanFactory和FactoryBean的区别

    BeanFactory

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

    FactoryBean

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

    • 第一类:普通Bean
    • 第二类:工厂Bean(记住:工厂Bean也是一种Bean,只不过这种Bean比较特殊,它可以辅助Spring实例化其它Bean对象。)

    工厂Bean的使用:注入自定义Date

    java.util.Date在Spring中被当做简单类型,简单类型在注入的时候可以直接使用value属性或value标签来完成。
    但我们之前已经测试过了,对于Date类型来说,采用value属性或value标签赋值的时候,对日期字符串的格式要求非常严格,必须是特殊格式的。其他格式是不会被识别的。

    所以我们可以使用FactoryBean接口对Bean的创建进行增强操作。

    定义一个学生类:Student

    public class Student {
        private Date birth;
    
        public void setBirth(Date birth) {
            this.birth = birth;
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "birth=" + birth +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    创建一个工厂Bean:DateFactoryBean类,实现FactoryBean

    public class DateFactoryBean implements FactoryBean<Date> {
        private String strDate;
    
        public DateFactoryBean(String strDate) {
            this.strDate = strDate;
        }
    
        @Override
        public Date getObject() throws Exception {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date date = sdf.parse(strDate);
            return date;
        }
    
        @Override
        public Class<?> getObjectType() {
            return null;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    spring.xml配置:

    	<bean id="date" class="com.bean.instantiation.bean.DateFactoryBean">
            <constructor-arg index="0" value="2020-10-11"/>
        </bean>
        <bean id="student" class="com.bean.instantiation.bean.Student">
            <property name="birth" ref="date"/>
        </bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    测试程序:

        @Test
        public void testStudentDate(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
            Student student = applicationContext.getBean("student", Student.class);
            System.out.println(student);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述

  • 相关阅读:
    关系模型的完整性约束:实体完整性 ,参照完整性,用户自定义完整性
    中国单反相机行业供需趋势及投资风险研究报告
    golang和mysql中的数据类型的对应
    Anaconda和Python的区别
    红蓝攻防演练怎样构建实战化网络安全防御体系
    2022-09-05 mysql/stonedb-物理存储层-数据间的关系
    在线旅游平台步入新时代,携程如何走出自己的路?
    QT国际化,语言翻译
    使用Psycopg2连接openGauss 3.0(python2)
    IDEA 新版本设置菜单展开
  • 原文地址:https://blog.csdn.net/weixin_45832694/article/details/127906721