zoukankan      html  css  js  c++  java
  • [译]9-spring bean的生命周期

    spring中bean的生命周期比较容易理解.bean在实例化之后有时需要调用某个初始化方法进行一些初始化的工作.同样的

    ,当bean在销毁之前有时需要做一些资源回收的工作.

    尽管bean在实例化和销毁的时候背后会发生很多事情.但是本章我们只会介绍bean实例化和销毁过程中会回调的两个生命

    周期方法.

    1.初始化回调方法

    当我们从spring IOC容器中拿到某个bean的实例的时,Spring IOC会按如下流程进行处理:

    • 首先spring IOC容器会使用new或者工厂类来实例化bean,再次过程中可能会使用构造器参数进行依赖项的注入
    • 在bean实例上调用setter方法进行依赖项的注入
    • 调用bean实例的初始化方法

    有两种方式指定bean的初始化方法,下面将分别介绍

    1.1.继承InitializingBean接口

    InitializingBean包含一个需要实现的方法-afterPropertiesSet,我们的bean可以继承InitializingBean接口并实现这个

    方法.在afterPropertiesSet方法书写bean的初始化代码.下面直接看一个例子.

    1.创建com.tutorialspoint.life_cycle.init_impl包,并在包中新建HelloWorld并实现InitializingBean接口,如下:

    package com.tutorialspoint.life_cycle.init_impl;
    
    import org.springframework.beans.factory.InitializingBean;
    
    public class HelloWorld implements InitializingBean{
        
        public HelloWorld(){
            System.out.println("constructor invoked ... ");
        }
        
        private String message;
    
        public String getMessage() {
            return message;
        }
    
        public void setMessage(String message) {
            System.out.println("set method invoked ... ");
            this.message = message;
        }
        
        public void afterPropertiesSet() throws Exception {
            System.out.println("afterPropertiesSet method invoked ... ");        
        }    
        
    }

    2.在src目录下创建life_cycle_init_impl.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-3.0.xsd">
       
       <bean id="helloWorld" class="com.tutorialspoint.life_cycle.init_impl.HelloWorld">
           <property name="message" value="Hello World!"></property>
       </bean>
    
    </beans>

    3.在com.tutorialspoint.life_cycle.init_impl包中创建MainApp.java类,内容如下:

    package com.tutorialspoint.life_cycle.init_impl;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class MailApp {
    
        public static void main(String[] args) {
            
            ApplicationContext context = new ClassPathXmlApplicationContext("life_cycle_init_impl.xml");
            
        }
    }

    4.运行程序,查看结果:

    从上述运行结果也可以看出.afterPropertiesSet方法调用的时机是:所有的依赖项注入完毕之后.

    1.2.使用xml配置文件中bean元素的init-method属性指定

    代码几乎完全一样,直接上代码.

    1.新建com.tutorialspoint.life_cycle.init_xml包,并在包中新建HelloWorld类,内容如下:

    package com.tutorialspoint.life_cycle.init_xml;
    
    public class HelloWorld {
        
        public HelloWorld(){
            System.out.println("constructor invoked ... ");
        }
        
        private String message;
    
        public String getMessage() {
            return message;
        }
    
        public void setMessage(String message) {
            System.out.println("set method invoked ... ");
            this.message = message;
        }
        //初始化方法
        public void init(){
            System.out.println("init method invoked ... ");
        }
        
    }

    2.在src目录下新建配置文件life_cycle_init_xml.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-3.0.xsd">
       
       <!-- 通过init-method属性指定初始化方法 -->
       <bean id="helloWorld" class="com.tutorialspoint.life_cycle.init_xml.HelloWorld" init-method="init">
           <property name="message" value="Hello World!"></property>
       </bean>
    
    </beans>

    3.在com.tutorialspoint.life_cycle.init_xml包中,新建MainApp.java类,内容如下:

    package com.tutorialspoint.life_cycle.init_xml;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class MailApp {
    
        public static void main(String[] args) {
            
            ApplicationContext context = new ClassPathXmlApplicationContext("life_cycle_init_xml.xml");
            
        }
    }

    4.运行程序,检查结果,如下:

    上面介绍完了两种指定bean的生命周期初始化方法的方式.那么我们在实际使用中应该使用哪一种方式呢?推荐第二种.

    1.第一种方式跟spring的代码紧耦合;第二种跟spring代码完全解耦

    2.第一种方式的初始化方法名不能修改,只能是afterPropertiesSet;第二种方式的初始化方法的名字可以任意修改.

    2.销毁回调方法

    当spring IOC容器销毁的时候(程序运行完毕JVM退出或者手动关闭)会调用bean的销毁回调方法,有如下两种方式:

    2.1.继承DisposableBean接口

    1.创建com.tutorialspoint.life_cycle.destroy_impl包,并在包中新建HelloWorld.java实现DisposableBean接口:

    package com.tutorialspoint.life_cycle.destroy_impl;
    
    import org.springframework.beans.factory.DisposableBean;
    
    public class HelloWorld implements DisposableBean{
        
        public HelloWorld(){
            System.out.println("constructor invoked ... ");
        }
        
        private String message;
    
        public String getMessage() {
            return message;
        }
    
        public void setMessage(String message) {
            System.out.println("set method invoked ... ");
            this.message = message;
        }
        
        //把回收代码放到destroy.destroy是DisposableBean接口中的方法
        @Override
        public void destroy() throws Exception {
            System.out.println("destroy method invoked ... ");
        }
    }

    2.在src目录下创建life_cycle_destroy_impl.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-3.0.xsd">
       
       <bean id="helloWorld" class="com.tutorialspoint.life_cycle.destroy_impl.HelloWorld">
           <property name="message" value="Hello World!"></property>
       </bean>
    
    </beans>

    3.在com.tutorialspoint.life_cycle.destroy_impl包中新建MainApp.java类,内容如下:

    package com.tutorialspoint.life_cycle.destroy_impl;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.AbstractApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class MainApp {
    
        public static void main(String[] args) {
            /**
             * 使用如下这行代码进行测试,发现并没有执行destroy方法,这是因为程序运行完毕之后,JVM直接退出.
             * 输入如下:
             * constructor invoked ... 
             * set method invoked ... 
             */
            //ApplicationContext context = new ClassPathXmlApplicationContext("life_cycle_destroy_impl.xml");
            
            /**
             * spring提供了AbstractApplicationContext类,该类中有两个非常有用的方法:close和registerShutdownHook
             * close方法提供了手动关闭spring IOC容器的实现
             * registerShutdownHook方法使spring容器订阅JVM退出的事件,JVM退出时会回调spring容器的close方法.
             */
            AbstractApplicationContext context = new ClassPathXmlApplicationContext("life_cycle_destroy_impl.xml");
            context.close();
            //context.registerShutdownHook();
            
        }
    }

    4.运行程序,检查结果:

    2.2.使用xml配置文件中bean元素的destroy-method属性指定

    直接上代码.

    1.新建com.tutorialspoint.life_cycle.destroy_xml包,并在包中新建HelloWorld.java,内容如下:

    package com.tutorialspoint.life_cycle.destroy_xml;
    
    public class HelloWorld {
        
        public HelloWorld(){
            System.out.println("constructor invoked ... ");
        }
        
        private String message;
    
        public String getMessage() {
            return message;
        }
    
        public void setMessage(String message) {
            System.out.println("set method invoked ... ");
            this.message = message;
        }
        
        public void destroy() {
            System.out.println("destroy method invoked ... ");
        }
    }

    2.在src目录下新建life_cycle_destroy_xml.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-3.0.xsd">
       
       <!-- 通过bean元素的destroy-method属性指定销毁回调方法 -->
       <bean id="helloWorld" class="com.tutorialspoint.life_cycle.destroy_xml.HelloWorld" destroy-method="destroy">
           <property name="message" value="Hello World!"></property>
       </bean>
    
    </beans>

    3.在com.tutorialspoint.life_cycle.destroy_xml包中新建MainApp.java类,内容如下:

    package com.tutorialspoint.life_cycle.destroy_xml;
    
    import org.springframework.context.support.AbstractApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class MainApp {
    
        public static void main(String[] args) {
            
            AbstractApplicationContext context = new ClassPathXmlApplicationContext("life_cycle_destroy_xml.xml");
            context.close();
        }
    }

    4.运行程序,检查结果:

    3.默认初始化和销毁方法

    程序中可能会多类都有相同的初始化或资源回收方法。如,有一个程序,程序中大量的类都有init初始化方法,同时也有

    destroy资源回收方法的话.我们可以通过指定<beans>元素的default-init-method和default-destroy-method属性

    来指定spring容器中bean的默认的初始化方法和销毁方法.如下:

    <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-3.0.xsd"
        default-init-method="init" 
        default-destroy-method="destroy">
    
       <bean id="..." class="...">
           <!-- collaborators and configuration for this bean go here -->
       </bean>
    
    </beans>
  • 相关阅读:
    array note
    前端开发规范
    java集合分类
    react native环境
    gulp
    关于如何在海量手机号中刷选出想要的手机号
    生成用户头像插件
    下拉加载
    阿里云人脸人体识别调试心得与备忘
    Sublime text3使用时有卡顿现象
  • 原文地址:https://www.cnblogs.com/sysman/p/4479176.html
Copyright © 2011-2022 走看看