SpringIoC组件的高级特性

简介: 一、Bean组件的周期与作用域 二、FactoryBean接口


一、Bean组件的周期与作用域

1.1 Bean组件的生命周期

什么是Bean的周期方法

    1. 我们可以在组件类中定义方法,然后当IoC容器实例化和销毁组件对象的时候进行调用!这两个方法我们成为生命周期方法!
    2. 类似于Servlet的init/ service/destroy方法,我们可以在周期方法完成初始化和释放资源等工作。
    3. Bean只有两种周期,init与destory,即初始化和销毁。

    1.2 Bean生命周期的代码实现

    创建组件类:

    package com.alphamilk.Ioc5;
    public class JavaBean {
        /*
        注意:使用周期方法时候,对应的方法必须满足以下几点
        1.无参
        2.返回值类型为void
         */
        public void init(){
            System.out.println("javaBean被初始化");
        }
        public  void destory(){
            System.out.println("JavaBean被正常销毁");
        }
    }

    image.gif

    创建对应的配置文件xml

    <?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">
    <!--    组件创建前面都是一样的,但是需要加上对应的周期方法:
            1.init-method 初始化组件方法 
            2.destroy-method 销毁组件方法
    -->
        <bean id="javaBean" class="com.alphamilk.Ioc5.JavaBean" init-method="init" destroy-method="destory"/>
    </beans>

    image.gif

    测试:

    package com.alphamilk.Ioc;
    import org.junit.jupiter.api.Test;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    public class newTest {
        @Test
        public void test(){
    //        创建容器对象
            ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("springioc-5.xml");
            /*
            注意,如果没有使用close函数,则会出现destroy方法无法调用的情况
            因为没有close下,ioc容器会意外死亡,就不会调用destroy方法
             */
    //        正常销毁组件对象
            applicationContext.close();
        }
    }

    image.gif

    image.gif编辑


    2.1 Bean标签的作用域

    什么是Bean标签的作用域

    一般情况下Bean的作用域对应两种形式,单例和多例模式,以下具体讲解单例与多例。

      • 单例:一般创建Bean中默认为单例模式singleton,其意思是在测试类中getBean的时候如果只有一个对应Bean标签,那么哪怕进行多次getBean返回,返回对象都是同一个。
      • 多例:指的是在测试类中getBean的时候,在使用getBean方法的时候,虽然只有一个标签,但是每一次调用都会产生一个新的Bean组件对象。

      具体创建多少个Bean的实例对象,由Bean的作用域Scope属性指定!一般都推荐用单例模式

      2.2 Scope作用域可选值

      取值 含义 创建对象的时机 默认值
      singleton 在 IOC 容器中,这个 bean 的对象始终为单实例 IOC 容器初始化时
      prototype 这个 bean 在 IOC 容器中有多个实例 获取 bean 时

      在WebApplicationContext中较为特殊,其scope多了两个取值

      取值 含义 创建对象的时机 默认值
      request 请求范围内有效的实例 每次请求
      session 会话范围内有效的实例 每次会话

      2.3 案例代码

      创建组件类对象

      package com.alphamilk.Ioc5;
      public class JavaBeanScope {
          public void doWork(){
              System.out.println("JavaBean is Working");
          }
      }

      image.gif

      配置对应单例与多例情况下

      在默认情况下不需要配置scpoe

      image.gif编辑

      测试代码:

      package com.alphamilk.Ioc;
      import com.alphamilk.Ioc5.JavaBeanScope;
      import org.junit.jupiter.api.Test;
      import org.springframework.context.ApplicationContext;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      public class newTest {
          @Test
          public void test(){
      //        创建Ioc容器
              ApplicationContext applicationContext = new ClassPathXmlApplicationContext("springioc-5.xml");
      //        通过容器获取Bean对象
              JavaBeanScope bean = applicationContext.getBean(JavaBeanScope.class);
              JavaBeanScope bean2 = applicationContext.getBean(JavaBeanScope.class);
      //        结果为False,因为采用多例模式下,每一次getBean,Ioc都会new一个新的JavaBeanScope对象
              System.out.println(bean==bean2);
          }
      }

      image.gif

      image.gif编辑


      二、FactoryBean接口

      1.1 什么是FactoryBean

        1. 在我们前面文章中提到,实现SpringIoc有两个接口,四个实现类。Factory就是两个接口中的父接口。
        2. 虽然Ioc容器会自动new一个对象,但是并不是所有的组件都是可以随便就new出来的,比如Mybatis。其最终是要构造Session操作数据库对象,而获取该对象需要先获取配置信息getResource(配置文件),然后构造SessionFactoryBuilder,再调用SessionFactoryBuilder函数Builder,最后获取到的SessionFactory还需要调用方法openSession。这种复杂的创建对象的过程一般的Ioc容器就无法实现。所以我们直接从其根源FactoryBean来设置该如何实例化对象。

        修改复杂实例化思路:

        image.gif编辑

        1.2  FactoryBean接口的常用方法

        方法名 方法描述
        T getObject() 返回由工厂创建的对象实例。该返回值将被存储到IoC容器中。
        boolean isSingleton() 如果此 FactoryBean 返回单例对象,则返回 true ,否则返回 false 。默认实现返回 true (注意,使用lombok插件可能会影响效果)。
        Class<?> getObjectType() 返回 getObject() 方法返回的对象类型。如果在创建之前不知道对象类型,则返回 null

        1.3  实现FactoryBean案例代码

        1.创建JavaBean需要实例化的子类

        package com.alphamilk.Ioc6;
        public class JavaBean {
            private String name;
            private int age;
        //    组件方法
            public void PrintInfo(){
                System.out.println(name+"的年龄是"+age);
            }
        }

        image.gif

        2.创建JavaBean需要实例化的工厂类

        package com.alphamilk.Ioc6;
        import org.springframework.beans.factory.FactoryBean;
        //泛型内容<>内填写返回的类型
        public class JavaBeanFactory implements FactoryBean<JavaBean> {
        //    如果子例对象需要DI(依赖注入)则需要进行桥梁连接
            private String name;
            public void setName(String name) {
                this.name = name;
            }
            private int age;
            public void setAge(int age) {
                this.age = age;
            }
            //    覆写如何实现实例化子类过程
            @Override
            public JavaBean getObject() throws Exception {
                JavaBean javaBean = new JavaBean();
                javaBean.setAge(age);
                javaBean.setName(name);
                return javaBean;
            }
        // 设置返回的类全定符
            @Override
            public Class<?> getObjectType() {
                return JavaBean.class;
            }
        }

        image.gif

        3.配置XML

        <?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 id="javaBeanFactory" class="com.alphamilk.Ioc6.JavaBeanFactory">
        <!--    由于是setter注入,所以用对应的注入方法-->
            <property name="name" value="黄飞宏"/>
            <property name="age" value="99"/>
        </bean>
        </beans>

        image.gif

        4.测试代码

        package com.alphamilk.Ioc;
        import com.alphamilk.Ioc5.JavaBeanScope;
        import com.alphamilk.Ioc6.JavaBean;
        import org.junit.jupiter.api.Test;
        import org.springframework.context.ApplicationContext;
        import org.springframework.context.support.ClassPathXmlApplicationContext;
        public class newTest {
            @Test
            public void test(){
        //  创建Ioc容器
                ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("springioc-6.xml");
        //        获取组件Bean
                JavaBean bean = (JavaBean) context.getBean("javaBeanFactory");
        //        调用Bean方法测试是否有效
                bean.PrintInfo();
            }
        }

        image.gif

        image.gif编辑

        总结一下FactoryBean的使用场景:

          1. 代理类的创建
          2. 第三方框架整合
          3. 复杂对象实例化等

          容易混淆--面试题 FactoryBean和BeanFactory区别

            1. **FactoryBean **是 Spring 中一种特殊的 bean,可以在 getObject() 工厂方法自定义的逻辑创建Bean!是一种能够生产其他 Bean 的 Bean。FactoryBean 在容器启动时被创建,而在实际使用时则是通过调用 getObject() 方法来得到其所生产的 Bean。因此,FactoryBean 可以自定义任何所需的初始化逻辑,生产出一些定制化的 bean。
            2. 一般情况下,整合第三方框架,都是通过定义FactoryBean实现!!!
            3. BeanFactory 是 Spring 框架的基础,其作为一个顶级接口定义了容器的基本行为,例如管理 bean 的生命周期、配置文件的加载和解析、bean 的装配和依赖注入等。BeanFactory 接口提供了访问 bean 的方式,例如 getBean() 方法获取指定的 bean 实例。它可以从不同的来源(例如 Mysql 数据库、XML 文件、Java 配置类等)获取 bean 定义,并将其转换为 bean 实例。同时,BeanFactory 还包含很多子类(例如,ApplicationContext 接口)提供了额外的强大功能。
            4. 总的来说,FactoryBean 和 BeanFactory 的区别主要在于前者是用于创建 bean 的接口,它提供了更加灵活的初始化定制功能,而后者是用于管理 bean 的框架基础接口,提供了基本的容器功能和 bean 生命周期管理。

            目录
            相关文章
            |
            5天前
            |
            缓存 Java uml
            SpringBoot2 | Spring IOC 流程中核心扩展接口的12个扩展点源码分析(十一)
            SpringBoot2 | Spring IOC 流程中核心扩展接口的12个扩展点源码分析(十一)
            48 0
            |
            5天前
            |
            Java Spring 容器
            面试题:Spring框架中,一个组件是怎样向自己内部注入组件的
            面试题:Spring框架中,一个组件是怎样向自己内部注入组件的
            16 0
            |
            8月前
            |
            XML Java 数据格式
            Spring Bean的生命周期和扩展点源码解读
            Spring Bean的生命周期和扩展点源码解读
            160 0
            |
            10月前
            |
            XML 敏捷开发 存储
            spring框架-概述(spring特性、生命周期)(一)
            spring框架-概述(spring特性、生命周期)(一)
            SpringBoot2学习(三):原生组件注入
            SpringBoot2学习(三):原生组件注入
            SpringBoot2学习(三):原生组件注入
            |
            XML 存储 Java
            聊聊 Spring 核心特性中的数据绑定 (DataBinder)
            Spring 的核心特性包括 IOC 容器、事件、资源管理、国际化、校验、数据绑定、类型转换、EL 表达式、AOP。其他特性可以轻易的在网络上找到很多资料,而数据绑定这个特性即便在 Spring 官网描述却也不太多。这是因为数据绑定主要应用于 Spring 内部,对于用户而言直接使用的场景并不多。如果想要深入理解 Spring 内部的运行机制,数据绑定是必须了解的一块内容。
            185 0
            |
            Java 数据库连接 Spring
            Spring 核心功能之一【IoC容器】依赖注入接口,层级包命名规范
            Spring 核心功能之一【IoC容器】依赖注入接口,层级包命名规范
            115 0
            Spring 核心功能之一【IoC容器】依赖注入接口,层级包命名规范
            |
            XML 存储 Java
            springIoc简述
            IoC(控制反转:Inverse of Control),又称作依赖注入,是一种重要的面向对象编程的法则来削减计算机程序的耦合问题,也是轻量级的Spring框架的核心。
            |
            监控 Java 容器
            spring5注解编程基础组件(三)
            spring5注解编程基础组件(三)
            204 0