手撸spring08: 将初始化和销毁方法交给Spring管理 取代static静态代码块更优雅

上一章中是在Bean注册后实行属性的填充,和初始化过程中的前置处理和后置处理.今天撸的这块代码,缺胳膊少腿的, 所以我决定一边跟着撸 一边解决问题,把那些缺的胳膊和腿补上!

两种形式可以实现这一章的需求, 一是通过实现Spring的默认类,重写方法,然后spring在执行时调用.

另一种则是写在配置文件中的属性,通过init-method和destroy-method来手动注册

定义初始化和销毁方法的接口

InitializingBean

初始化方法,言简意赅的方法名,在初始化后执行

package com.linnine.spring.beans.factory;

public interface InitializingBean {

    /**
     * 在属性填充后调用
     * @throws Exception
     */
    void afterPropertiesSet() throws Exception;

}

DisposableBean

public interface DisposableBean {

    /**
     * 销毁方法
     * @throws BeansException
     */
    void destroy() throws Exception;
}

在spring中比较常用的存在,在需要结合spring实现的组件中很常见,经常用来进行一些参数的初始化和销毁操作,比如接口暴露/数据库数据读取/配置文件加载等待.

Bean定义新增初始化和销毁方法

package com.linnine.spring.beans.factory.config;

import com.linnine.spring.beans.PropertyValues;
import lombok.Data;

@Data
public class BeanDefinition {

    private Class beanClass;

    //补充属性
    private PropertyValues propertyValues;

    //初始化
    private String initMethodName;

    //销毁
    private String destroyMethodName;

    //这里升级为只传类型,而不是实例 在需要的时候才去实例化
    public BeanDefinition(Class beanClass){
        this.beanClass=beanClass;
        //如果没有就传个空的 避免后去捞的时候空指针异常
        this.propertyValues=new PropertyValues();
    }

    public BeanDefinition(Class beanClass, PropertyValues propertyValues) {
        this.beanClass = beanClass;
        this.propertyValues = propertyValues;
    }
}

执行Bean对象的初始化方法

AbstractAutowireCapableBeanFactory

package com.linnine.spring.beans.factory.support;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.linnine.spring.beans.BeansException;
import com.linnine.spring.beans.PropertyValue;
import com.linnine.spring.beans.PropertyValues;
import com.linnine.spring.beans.factory.DisposableBean;
import com.linnine.spring.beans.factory.InitializingBean;
import com.linnine.spring.beans.factory.config.AutowireCapableBeanFactory;
import com.linnine.spring.beans.factory.config.BeanDefinition;
import com.linnine.spring.beans.factory.config.BeanPostProcessor;
import com.linnine.spring.beans.factory.config.BeanReference;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

@Getter
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {

    private InstantiationStrategy instantiationStrategy =new CglibSubclassingInstantiationStrategy();

    @Override
    protected Object createBean(String beanName, BeanDefinition beanDefinition,Object[] args) throws BeansException {
        Object bean;
        bean = createBeanInstance(beanDefinition,args);
        //补充属性
        applyPropertyValues(bean,beanDefinition);
        //执行bean的初始化方法和BeanPostProcessor的前置方法和后置方法
        bean = initializeBean(beanName,bean,beanDefinition);

        //注册 有实现 DisposableBean 接口的bean对象
        registerDisposableBeanIfNecessary(beanName, bean, beanDefinition);

        addSingletonBean(beanName,bean);
        return bean;
    }

    protected void registerDisposableBeanIfNecessary(String beanName, Object bean, BeanDefinition beanDefinition){
        if (bean instanceof DisposableBean || StrUtil.isNotEmpty(beanDefinition.getDestroyMethodName())) {
            registerDisposableBean(beanName, new DisposableBeanAdapter(bean, beanName, beanDefinition));
        }
    }

    private Object initializeBean(String beanName, Object bean, BeanDefinition beanDefinition){
        //执行前置处理器
        Object wrappedBean=applyBeanPostProcessorsBeforeInitialization(bean,beanName);
        //待完成 执行初始化方法
        try {
            invokeInitMethods(beanName, wrappedBean, beanDefinition);
        } catch (Exception e) {
            throw new BeansException("Invocation of init method of bean[" + beanName + "] failed", e);
        }
        //执行后处理器
        wrappedBean = applyBeanPostProcessorsAfterInitialization(bean, beanName);

        return wrappedBean;
    }


    /**
     * 08 完善初始化方法
     * @param beanName
     * @param bean
     * @param beanDefinition
     * @throws Exception
     */
    private void invokeInitMethods(String beanName, Object bean, BeanDefinition beanDefinition) throws Exception {

        //执行初始化
        if (bean instanceof InitializingBean){
            ((InitializingBean) bean).afterPropertiesSet();
        }
        //获取初始化方法名称
        String initMethodName = beanDefinition.getInitMethodName();
        if (StringUtils.isNotEmpty(initMethodName)){
            //去类里面获取方法
            Method initMethod = beanDefinition.getBeanClass().getMethod(initMethodName);
            if (null == initMethod){
                throw new BeansException("Could not find an init initMethod named '" + initMethodName + "' on bean with name '" + beanName + "'");
            }
            //执行初始化方法
            initMethod.invoke(bean);
        }

    }

    private Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName){
        Object result =existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessBeforeInitialization(result, beanName);
            if (null != current) {
                result =current;
            }
        }
        return result;
    }
    protected Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName){
        Object result =existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessAfterInitialization(result, beanName);
            if (null != current) {
                result =current;
            }
        }
        return result;
    }

    protected Object createBeanInstance( BeanDefinition beanDefinition,Object... args){
        Constructor constructor =null;
        Class beanClass = beanDefinition.getBeanClass();
        //获取所有的构造方法
        Constructor[] declaredConstructors = beanClass.getDeclaredConstructors();
        //简单对比 spring还会对比类型
        for (Constructor ctor : declaredConstructors) {
            if (null!=args && ctor.getParameterTypes().length ==args.length){
                constructor=ctor;
                break;
            }
        }
        //创建
        return getInstantiationStrategy().instantiate(beanDefinition,constructor,args);
    }

    //手撸05新增
    protected void applyPropertyValues(Object bean, BeanDefinition beanDefinition){
        //取出填入的属性
        PropertyValues propertyValues = beanDefinition.getPropertyValues();
        for (PropertyValue propertyValue : propertyValues.getPropertyValues()) {
            String name = propertyValue.getName();
            Object value = propertyValue.getValue();
            //如果是个实例对象
            if (value instanceof BeanReference){
                BeanReference  beanReference=(BeanReference)value;
                //通过bean名去获取bean 跳过循环依赖 后面再补充
                value = getBean(beanReference.getBeanName());
            }
            //通过名称注入属性
            BeanUtil.setFieldValue(bean,name,value);
        }
    }

}

在Bean创建时 注册 销毁方法对象

这里只是注册进去,在需要时调用

package com.linnine.spring.beans.factory.support;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.linnine.spring.beans.BeansException;
import com.linnine.spring.beans.PropertyValue;
import com.linnine.spring.beans.PropertyValues;
import com.linnine.spring.beans.factory.DisposableBean;
import com.linnine.spring.beans.factory.InitializingBean;
import com.linnine.spring.beans.factory.config.AutowireCapableBeanFactory;
import com.linnine.spring.beans.factory.config.BeanDefinition;
import com.linnine.spring.beans.factory.config.BeanPostProcessor;
import com.linnine.spring.beans.factory.config.BeanReference;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

@Getter
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {

    private InstantiationStrategy instantiationStrategy =new CglibSubclassingInstantiationStrategy();

    @Override
    protected Object createBean(String beanName, BeanDefinition beanDefinition,Object[] args) throws BeansException {
        Object bean;
        bean = createBeanInstance(beanDefinition,args);
        //补充属性
        applyPropertyValues(bean,beanDefinition);
        //执行bean的初始化方法和BeanPostProcessor的前置方法和后置方法
        bean = initializeBean(beanName,bean,beanDefinition);

        //注册 有实现 DisposableBean 接口的bean对象
        registerDisposableBeanIfNecessary(beanName, bean, beanDefinition);

        addSingletonBean(beanName,bean);
        return bean;
    }

    /**
     * 08新增 注册销毁方法类
     * @param beanName
     * @param bean
     * @param beanDefinition
     */
    protected void registerDisposableBeanIfNecessary(String beanName, Object bean, BeanDefinition beanDefinition){
        if (bean instanceof DisposableBean || StrUtil.isNotEmpty(beanDefinition.getDestroyMethodName())) {
            registerDisposableBean(beanName, new DisposableBeanAdapter(bean, beanName, beanDefinition));
        }
    }

    private Object initializeBean(String beanName, Object bean, BeanDefinition beanDefinition){
        //执行前置处理器
        Object wrappedBean=applyBeanPostProcessorsBeforeInitialization(bean,beanName);
        //待完成 执行初始化方法
        try {
            invokeInitMethods(beanName, wrappedBean, beanDefinition);
        } catch (Exception e) {
            throw new BeansException("Invocation of init method of bean[" + beanName + "] failed", e);
        }
        //执行后处理器
        wrappedBean = applyBeanPostProcessorsAfterInitialization(bean, beanName);

        return wrappedBean;
    }


    /**
     * 08 完善初始化方法
     * @param beanName
     * @param bean
     * @param beanDefinition
     * @throws Exception
     */
    private void invokeInitMethods(String beanName, Object bean, BeanDefinition beanDefinition) throws Exception {

        //执行初始化
        if (bean instanceof InitializingBean){
            ((InitializingBean) bean).afterPropertiesSet();
        }
        //获取初始化方法名称
        String initMethodName = beanDefinition.getInitMethodName();
        if (StringUtils.isNotEmpty(initMethodName)){
            //去类里面获取方法
            Method initMethod = beanDefinition.getBeanClass().getMethod(initMethodName);
            if (null == initMethod){
                throw new BeansException("Could not find an init initMethod named '" + initMethodName + "' on bean with name '" + beanName + "'");
            }
            //执行初始化方法
            initMethod.invoke(bean);
        }

    }

    private Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName){
        Object result =existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessBeforeInitialization(result, beanName);
            if (null != current) {
                result =current;
            }
        }
        return result;
    }
    protected Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName){
        Object result =existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessAfterInitialization(result, beanName);
            if (null != current) {
                result =current;
            }
        }
        return result;
    }

    protected Object createBeanInstance( BeanDefinition beanDefinition,Object... args){
        Constructor constructor =null;
        Class beanClass = beanDefinition.getBeanClass();
        //获取所有的构造方法
        Constructor[] declaredConstructors = beanClass.getDeclaredConstructors();
        //简单对比 spring还会对比类型
        for (Constructor ctor : declaredConstructors) {
            if (null!=args && ctor.getParameterTypes().length ==args.length){
                constructor=ctor;
                break;
            }
        }
        //创建
        return getInstantiationStrategy().instantiate(beanDefinition,constructor,args);
    }

    //手撸05新增
    protected void applyPropertyValues(Object bean, BeanDefinition beanDefinition){
        //取出填入的属性
        PropertyValues propertyValues = beanDefinition.getPropertyValues();
        for (PropertyValue propertyValue : propertyValues.getPropertyValues()) {
            String name = propertyValue.getName();
            Object value = propertyValue.getValue();
            //如果是个实例对象
            if (value instanceof BeanReference){
                BeanReference  beanReference=(BeanReference)value;
                //通过bean名去获取bean 跳过循环依赖 后面再补充
                value = getBean(beanReference.getBeanName());
            }
            //通过名称注入属性
            BeanUtil.setFieldValue(bean,name,value);
        }
    }

}

钩子函数调用销毁方法

package com.linnine.spring.context;

import com.linnine.spring.beans.BeansException;

public interface ConfigurableApplicationContext extends ApplicationContext{

    /**
     * 刷新容器
     * @throws BeansException
     */
    void refresh() throws BeansException;

    /**
     * 钩子
     */
    void registerShutdownHook();

    /**
     * 关闭
     */
    void close() throws Exception;
}

AbstractApplicationContext

实现钩子

package com.linnine.spring.context.support;


import com.linnine.spring.beans.BeansException;
import com.linnine.spring.beans.factory.ConfigurableListableBeanFactory;
import com.linnine.spring.beans.factory.config.BeanFactoryPostProcessor;
import com.linnine.spring.beans.factory.config.BeanPostProcessor;
import com.linnine.spring.context.ConfigurableApplicationContext;
import com.linnine.spring.core.io.DefaultResourceLoader;

import java.util.Map;

/**
 * 应用上下文 抽象类实现
 */
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {

    @Override
    public void refresh() throws BeansException {
        //创建beanFactory, 并加载BeanDefinition
        refreshBeanFactory();
        //获取BeanFactory
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        //在Bean实例化前 调用后处理器
        invokeBeanFactoryPostProcessors(beanFactory);
        //注册bean处理器
        registerBeanPostProcessors(beanFactory);
        //提前实例化单例对象
        beanFactory.preInstantiateSingletons();
    }


    private void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        //获取所有工厂后处理器
        Map<String, BeanFactoryPostProcessor> beanFactoryPostProcessorMap = beanFactory.getBeansOfType(BeanFactoryPostProcessor.class);
        //遍历去处理
        for (BeanFactoryPostProcessor beanFactoryPostProcessor : beanFactoryPostProcessorMap.values()) {
            beanFactoryPostProcessor.postProcessorBeanFactory(beanFactory);
        }
    }
    private void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        Map<String, BeanPostProcessor> beanPostProcessorMap = beanFactory.getBeansOfType(BeanPostProcessor.class);
        for (BeanPostProcessor beanPostProcessor : beanPostProcessorMap.values()) {
            beanFactory.addBeanPostProcessor(beanPostProcessor);
        }
    }

    protected abstract ConfigurableListableBeanFactory getBeanFactory();

    protected abstract void refreshBeanFactory();


    @Override
    public void registerShutdownHook(){
        Runtime.getRuntime().addShutdownHook(new Thread(this::close));
    }

    /**
     * 关闭
     */
    @Override
    public void close(){
        getBeanFactory().destroySingletons();
    }

}

然后这里就上面这个方法,自己补了一下!

getBeanFactory().destroySingletons();

ConfigurableListableBeanFactory加个接口就不贴代码了

直接贴实现类里的代码

package com.linnine.spring.beans.factory.support;

import com.linnine.spring.beans.factory.DisposableBean;
import com.linnine.spring.beans.factory.config.SingletonBeanRegistry;

import java.util.HashMap;
import java.util.Map;
public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {

    private final Map<String, Object> singletonObjects = new HashMap<>();
    private final Map<String, DisposableBean> disposableBeans = new HashMap<>();

    /**
     * 实现获取单例的方法
     *
     * @param beanName
     * @return
     */
    @Override
    public Object getSingleton(String beanName) {
        return singletonObjects.get(beanName);
    }

    /**
     * 提供一个包保护的方法 可以被继承此类的其他类调用
     *
     * @param beanName
     * @param singletonObject
     */
    protected void addSingletonBean(String beanName, Object singletonObject) {
        singletonObjects.put(beanName, singletonObject);
    }

    protected void registerDisposableBean(String beanName, DisposableBeanAdapter disposableBeanAdapter) {
        disposableBeans.put(beanName,disposableBeanAdapter);
    }

    public void destroySingletons() {
        for (DisposableBean value : disposableBeans.values()) {
            try {
                value.destroy();
            } catch (Exception exception) {
                exception.printStackTrace();
            }
        }
    }

}

然后是测试用的业务类

UserDao使用配置文件加载初始方法和清除方法, 取代了原本的static静态代码块

package com.linnine.spring.bean.dao;

import java.util.HashMap;
import java.util.Map;

public class UserDao {
    private static Map<String, String> hashMap = new HashMap<>();

    /**
     * 取代静态代码块,让spring来实现更优雅
     */
    public void initDataMethod(){
        System.out.println("执行:init-method");
        hashMap.put("10001", "小傅哥");
        hashMap.put("10002", "八杯水");
        hashMap.put("10003", "阿毛");
    }

    /**
     * spring 代为清除数据
     */
    public void destroyDataMethod(){
        System.out.println("执行:destroy-method");
        hashMap.clear();
    }

    public String queryUserName(String uId) {
        return hashMap.get(uId);
    }
}

配置文件 主要改了userDao的配置

<bean id="userDao" class="com.linnine.spring.bean.dao.UserDao" init-method="initDataMethod" destroy-method="destroyDataMethod"/>

另外一种则是直接实现上面的两个接口

package com.linnine.spring.bean.service;


import com.linnine.spring.bean.dao.UserDao;
import com.linnine.spring.beans.factory.DisposableBean;
import com.linnine.spring.beans.factory.InitializingBean;
import lombok.Data;

@Data
public class UserService implements InitializingBean, DisposableBean {

    private String uId;

    private String company;

    private String location;

    private UserDao userDao;

    public String queryUserInfo(){
        return userDao.queryUserName(uId)+uId+company+location;
    }


    @Override
    public void afterPropertiesSet() {
        System.out.println("执行:UserService.afterPropertiesSet");
    }

    @Override
    public void destroy() {
        System.out.println("执行:UserService.destroy");
    }


}

开始测试

@Test
public void test_XML(){
    //初始化
    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
    applicationContext.registerShutdownHook();

    UserService userService = (UserService) applicationContext.getBean("userService", UserService.class);

    String s = userService.queryUserInfo();
    System.out.println("测试结果"+s);
}

目标结果

执行:init-method
执行:UserService.afterPropertiesSet
测试结果:小傅哥,腾讯,深圳
执行:UserService.destroy
执行:destroy-method

我的结果1:

执行:UserService.afterPropertiesSet
测试结果null10001腾讯深圳
执行:UserService.destroy

userDao的都没执行, 应该是没加载配置,去读取配置文件的类里面补充一下,这里只放 修改了的那一段代码

public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
	...
	private void doLoadBeanDefinitions(InputStream inputStream) throws ClassNotFoundException {
		Document doc = XmlUtil.readXML(inputStream);
        Element root = doc.getDocumentElement();
        NodeList childNodes = root.getChildNodes();

        for (int i = 0; i < childNodes.getLength();i++) {
            //判断元素
            if (!(childNodes.item(i) instanceof Element)) continue;
            //判断对象
            if (!"bean".equals(childNodes.item(i).getNodeName())) continue;

            //解析标签
            Element bean = (Element) childNodes.item(i);
            String id = bean.getAttribute("id");
            String name = bean.getAttribute("name");
            String className = bean.getAttribute("class");
            //08 读取初始化方法 和销毁方法
            String initMethodName = bean.getAttribute("init-method");
            String destroyMethodName = bean.getAttribute("destroy-method");

            //获取Class 方便获取类名
            Class<?> clazz = Class.forName(className);
            //优先级 id>name
            String beanName = StrUtil.isNotEmpty(id)?id:name;
            //如果取不到 就从类里面取
            if (StrUtil.isEmpty(beanName)){
                beanName = StrUtil.lowerFirst(clazz.getSimpleName());
            }

            //开始定义Bean
            BeanDefinition beanDefinition = new BeanDefinition(clazz);
            //08 加入到定义中
            beanDefinition.setInitMethodName(initMethodName);
            beanDefinition.setDestroyMethodName(destroyMethodName);
            //读取属性并填充
            NodeList beanNodeList = bean.getChildNodes();
            for (int j = 0; j <beanNodeList.getLength(); j++) {
                if (!(beanNodeList.item(j) instanceof Element)) continue;
                //判断标签是否为属性
                if (!"property".equals(beanNodeList.item(j).getNodeName())) continue;

                Element property = (Element) beanNodeList.item(j);
                String attrName = property.getAttribute("name");
                String attrValue = property.getAttribute("value");
                String attrRef = property.getAttribute("ref");
                //获取属性值
                Object value=StrUtil.isNotEmpty(attrRef)?(BeanReference)()->attrRef:attrValue;
                PropertyValue propertyValue =new PropertyValue(attrName,value);
                beanDefinition.getPropertyValues().addPropertyValue(propertyValue);
            }
            if (getRegistry().containsBeanDefinition(beanName)){
                throw new BeansException("Duplicate beanName[" + beanName + "] is not allowed");
            }
            // 注册 BeanDefinition
            getRegistry().registerBeanDefinition(beanName, beanDefinition);

        }
	}
	...
}

执行结果02:

执行:init-method
执行:UserService.afterPropertiesSet
测试结果小傅哥10001腾讯深圳
执行:UserService.destroy

奇怪 没有执行userDao的销毁方法

问题找到了,判断的地方判断错了

DisposableBeanAdapter

@Override
    public void destroy() throws Exception{

        if (bean instanceof DisposableBean){
            ((DisposableBean)bean).destroy();
        }else {
            // 2. 配置信息 destroy-method {判断是为了避免二次执行销毁}
        if (StringUtils.isNotEmpty(destroyMethodName)&& !(bean instanceof DisposableBean && "destroy".equals(this.destroyMethodName))){
                Method destroyMethod = bean.getClass().getMethod(destroyMethodName);
                destroyMethod.invoke(bean);
            }

        }

    }

执行:init-method
执行:UserService.afterPropertiesSet
测试结果:小傅哥10001腾讯深圳
销毁方法destroyDataMethod
执行:destroy-method
执行:UserService.destroy
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值