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的实现。

  • 相关阅读:
    mysql不停库不锁表在线主从配置
    MySQL5.7不停机不锁表主从同步实战
    另类 k8s 集群灾难恢复方法:用 master 服务器镜像恢复出新集群
    我在新西兰卖挖掘机之续篇十八------坚持的秘诀(坚持的秘诀就2条,第一是初始摩擦力要足够小(开头不能太困难,时间不能太久);第二是坚持的事情能够不断地给你提供某种真实的好处)(其实就是正反馈,加上一点点兴趣)
    分布式系统中那些不靠谱任务-CAP 到底是什么
    分布式系统架构中关于切分数据库事务的 ACID 性质的可用性与性能-BASE 理论和CAP 定理
    SSO协议-SAML和OAuth2
    领域建模
    基于 Docker 容器Net Core微服务部署 Nginx 集群架构
    消息队列和分布式锁
  • 原文地址:https://www.cnblogs.com/qiankunli/p/4947646.html
Copyright © 2011-2022 走看看