美文网首页SpringBoot
Spring容器创建对象的时机

Spring容器创建对象的时机

作者: HeloWxl | 来源:发表于2020-03-25 12:01 被阅读0次

    Spring容器创建对象的时机

    1、默认的情况下,启动spring容器时,编创建对象,(遇到bean便创建对象)

    测试:
    在HelloIoc.java中添加构造方法

    /**
     * @author wangxl
     * @ClassName HelloIoc
     * @Description TODO
     * @date 2019/10/14 17:29
     */
    public class HelloIoc {
    
      //默认构造函数
      public HelloIoc() {
        System.out.println("Hello default Constructor");
      }
      
      /**
       * sayHello方法
       */
      public void sayHello() {
        System.out.println("Hello IOC");
      }
      
    }
    
    • 在 applicationContext.xml 文件中添加 bean(由于上面我们通过三种方式来创建对象了,里面已经有三个bean了)
    • 启动 Spring 容器,查看无参构造函数的打印次数
      测试:
     /**
         * 只启动Spring容器
         */
        @Test
        public void whenCreateObject(){
            ApplicationContext context =
                new ClassPathXmlApplicationContext("applicationContext.xml");
        }
    

    结果:

    十月 17, 2019 2:00:08 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
    信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@5ccd43c2: startup date [Thu Oct 17 14:00:08 CST 2019]; root of context hierarchy
    十月 17, 2019 2:00:09 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
    信息: Loading XML bean definitions from class path resource [applicationContext.xml]
    Hello default Constructor
    Hello default Constructor
    实例工厂方法构造函数
    Hello default Constructor
    

    2、在spring的配置文件bean中有一个属性 lazy-init="default/true/false"

    ①、如果lazy-init为"default/false"在启动spring容器时创建对象(默认情况)
    ②、如果lazy-init为"true",在context.getBean时才要创建对象


    image.png

    测试结果:

    如果lazy-init为"default/false"在启动spring容器时创建对象(默认情况),没有getBean()

    十月 17, 2019 2:02:45 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
    信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@5ccd43c2: startup date [Thu Oct 17 14:02:45 CST 2019]; root of context hierarchy
    十月 17, 2019 2:02:46 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
    信息: Loading XML bean definitions from class path resource [applicationContext.xml]
    Hello default Constructor
    实例工厂方法构造函数
    Hello default Constructor
    
    

    当lazy-init = "true" 时,我们执行getbean()方法,Spring容器才会去创建对象。

        @Test
        public void iocTest() {
            //1.启动spring容器
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
            //2.从spring容器中取出数据
            HelloIoc ioc = (HelloIoc) applicationContext.getBean("helloIoc");
        }
    

    测试结果:

    十月 17, 2019 2:05:22 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
    信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@5ccd43c2: startup date [Thu Oct 17 14:05:22 CST 2019]; root of context hierarchy
    十月 17, 2019 2:05:23 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
    信息: Loading XML bean definitions from class path resource [applicationContext.xml]
    Hello default Constructor
    实例工厂方法构造函数
    Hello default Constructor
    Hello default Constructor
    

    小结:

    第一种情况下:

    在启动Spring容器的时候,会检查 Spring容器的配置文件的正确性,如果再结合tomcat,当spring容器不能正常启动时,整个tomcat就不能正常启动。但是这样的缺点就是把一些bean过早的放在了内存中,如果有数据的话,则对内存就是一个消耗。

    在第二种情况下:

    可以较少内存消耗,但是不容易发生错误。

    Spring的Bean中的 scope属性

    • 1、默认的scope的值是singleton,即产生的对象是单例的。
      applicationContext.xml 文件中配置:
    <bean id="helloIoc" scope="singleton" class="com.ys.ioc.HelloIoc" ></bean>
    

    测试验证

    //spring 容器默认产生对象是单例的 scope="singleton"
        @Test
        public void test_scope_single_CreateObject(){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            HelloIoc hello1 = (HelloIoc) context.getBean("helloIoc");
            HelloIoc hello2 = (HelloIoc) context.getBean("helloIoc");
            System.out.println(hello1.equals(hello2)); //true
        }
    
    • 2、scope=“prototype”
       多例模式,并且spring容器启动的时候并不会创建对象,而是在得到 bean 的时候才会创建对象

    applicationContext.xml 文件中配置:

    <bean id="helloIoc" scope="prototype" class="com.ys.ioc.HelloIoc" ></bean>
    

    测试验证

    ///spring 容器默认产生对象是单例的 scope="prototype"
        @Test
        public void test_scope_prototype_CreateObject(){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            HelloIoc hello1 = (HelloIoc) context.getBean("helloIoc");
            HelloIoc hello2 = (HelloIoc) context.getBean("helloIoc");
            System.out.println(hello1.equals(hello2)); //false
        }
    

    总结:

    在单例的模式下,启动spring容器,便会创建对象;在多例模式下,启动容器不会创建对象,获得bean的时候才会创建对象。

    Spring的Bean中的生命周期

    • 创建 SpringLifeCycle.java
    /**
     * Spring 容器的生命周期
     * @author hadoop
     *
     */
    public class SpringLifeCycle {
        public SpringLifeCycle(){
            System.out.println("SpringLifeCycle");
        }
        //定义初始化方法
        public void init(){
            System.out.println("init...");
        }
        //定义销毁方法
        public void destroy(){
            System.out.println("destroy...");
        }
         
        public void sayHello(){
            System.out.println("say Hello...");
        }
    }
    
    • applicationContext.xml
        <bean id="springLifeCycle" init-method="init" destroy-method="destroy" class="com.ys.ioc.SpringLifeCycle"></bean>
    
    
    • 测试
    //spring 容器的初始化和销毁
        @Test
        public void testSpringLifeCycle(){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            SpringLifeCycle hello = (SpringLifeCycle) context.getBean("springLifeCycle");
             
            hello.sayHello();
             
            //销毁spring容器
            ClassPathXmlApplicationContext classContext = (ClassPathXmlApplicationContext) context;
            classContext.close();
        }
    
    • 控制台打印如下:


      image.png
    • 分析:spring 容器的声明周期
      1、spring容器创建对象
      2、执行init方法
      3、调用自己的方法
      4、当spring容器关闭的时候执行destroy方法
       注意:当scope为"prototype"时,调用 close() 方法时是不会调用 destroy 方法的

    相关文章

      网友评论

        本文标题:Spring容器创建对象的时机

        本文链接:https://www.haomeiwen.com/subject/qlwmmctx.html