zoukankan      html  css  js  c++  java
  • 自己动手写spring(五) bean的生命周期管理

    前言

    众所周知,使用Class的newInstance方法,就算是调用了bean的构造方法。bean是不能控制自己何年何月何日生(死)的,但bean可以和bean工厂约定一些规则(也就是实现特定的方法),决定下生死时刻要做些什么。

    bean生命周期管理,主要涉及到标签中的init-method,destroy-method以及InitializingBean,DisposableBean接口。

    InitializingBean

    调用时机,当一个bean构造完成的时候调用。对前文和反射概念有一定了解的童鞋来说,实现起来不难。

    public class BeanFactory {
    
    	public Object getBean(String beanId) throws Exception {
    		Object obj = beanId2Class.get(beanId);
    		if (obj != null) {
    			return obj;
    		}
    		obj = getBeanFromXml(beanId);
    		obj = getBeanFromAnnotation(beanId);
    		// 为了不给BeanFactory类增加负担,我们将这个逻辑提出来
    		InitializingBeanProcessor.process(obj, beanId2Bean.get(beanId),beanId2Clazz.get(beanId));
    		return obj;
    	}
    }
    
    public class InitializingBeanProcessor {
    	public static void process(Object obj, Bean bean,Class clazz) throws Exception {		
    		Class[] intfs = clazz.getInterfaces();
    		for(Class intf : intfs){
    			if(intf.getSimpleName().equals("InitializingBean")){
    				Method m = clazz.getMethod("afterPropertiesSet", null);
    				m.invoke(obj, null);
    				break;
    			}
    		}
    	}
    }
    

    init-method

    <bean id="beanA" name="test" class="org.lqk.lspring2.bean.BeanA" init-method="init" destroy-method="close">
    	<property name="beanB" ref="beanB" />
    	<property name="title" value="studentA" />
    </bean>
    

    为bean标签类中添加init-method和destroy-method属性,并调用它们,也不是难事。

    public class InitializingBeanProcessor {
    	public static void process(Object obj, Bean bean,Class clazz) throws Exception {
    	    // 处理init-method标签
    		String initMethodName = bean.getInitMethodName();
    		if(StringUtils.isNotEmpty(initMethodName)){
    			Method m = clazz.getMethod(initMethodName, null);
    			m.invoke(obj, null);
    		}
    		// 处理InitializingBean的afterPropertiesSet方法
    		Class[] intfs = clazz.getInterfaces();
    		for(Class intf : intfs){
    			if(intf.getSimpleName().equals("InitializingBean")){
    				Method m = clazz.getMethod("afterPropertiesSet", null);
    				m.invoke(obj, null);
    				break;
    			}
    		}
    	}
    }
    

    DisposableBean和destroy-method

    何时调用DisposableBean的方法和destroy-method,当然是系统运行结束退出的时候,但系统什么时候退出呢?这就用到了shutdownHook(这可是java基础喔,在spring之前就有喔)。

    public class BeanFactory {
        private Thread shutdownHook;
        public BeanFactory() {
    		try {
    			loadXml();
    			loadAnnotation();
    			registerShutdownHook();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
        }
        public void registerShutdownHook() {
    		if (this.shutdownHook == null) {
    			// No shutdown hook registered yet.
    			this.shutdownHook = new Thread() {
    				@Override
    				public void run() {
    					destroyBeans();
    				}
    			};
    			Runtime.getRuntime().addShutdownHook(this.shutdownHook);
    		}
    	}
    	protected void destroyBeans() {
    		try {
    			DisposableBeanProcessor.process(beanId2Class, beanId2Bean,beanId2Clazz);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    }
    

    DisposableBeanProcessor与InitializingBeanProcessor的逻辑类似,此处不在赘述。

    下文,我们将讨论工厂bean的实现。

  • 相关阅读:
    JavaScript常用函数和方法
    Django中csrf错误
    LVS+Keepalived负载均衡配置
    CSP-S2019 游记
    三角函数公式整理
    LGOJP3193 [HNOI2008]GT考试
    BZOJ3790. 神奇项链
    BZOJ4241: 历史研究
    LGOJP2051 [AHOI2009]中国象棋
    AT2000 Leftmost Ball
  • 原文地址:https://www.cnblogs.com/qiankunli/p/4947646.html
Copyright © 2011-2022 走看看