如何实现bean初始化摧毁方法的注入

作者:Anoxia1 时间:2023-07-22 05:14:31 

实现 bean 初始化、摧毁方法的配置与处理

spring支持我们自定义 bean 的初始化方法和摧毁方法。配置方式可以通过 xml 的 init-methoddestory-method配置,或者实现 InitializingBeanDisposableBean接口,来完成自定义的初始化和bean的销毁。 在项目开发过程中,相信最多看到的是 @PostConstruct 注解标识的方法来进行bean的初始化。

@PostConstruct 是 Spring Framework 提供的注解,可以用于在 Bean 实例化之后执行初始化操作

通过xml配置定义初始化、摧毁方法

BeanDefinition 里面添加 initMethodName、和 destoryMethodName 属性,来记录通过配置注入的初始化和摧毁方法名称。然后在解析 xml 文件的 cn.anoxia.springframework.beans.factory.xml.XmlBeanDefinitionReader#doLoadBeanDefinitions方法中,完成 属性的注入。

protected void doLoadBeanDefinitions(InputStream inputStream) throws Exception {
       Document doc = XmlUtil.readXML(inputStream);
       Element root = doc.getDocumentElement();
       NodeList childNodes = root.getChildNodes();
       for (int i = 0; i < childNodes.getLength(); i++) {
           ....
           String initMethod = bean.getAttribute("init-method");
           String destroyMethod = bean.getAttribute("destroy-method");
           Class<?> clazz = Class.forName(calssName);
           String beanName = StrUtil.isNotEmpty(id) ? id : name;
           if (StrUtil.isEmpty(beanName)){
               beanName = StrUtil.lowerFirst(clazz.getSimpleName());
           }
           // 定义bean
           BeanDefinition beanDefinition = new BeanDefinition(clazz);
           // 设置初始化、摧毁方法
           beanDefinition.setInitMethodName(initMethod);
           beanDefinition.setDestoryMethodName(destroyMethod);
           ....
       }
   }

通过实现接口

实现 InitializingBean,DisposableBean 并实现里面的方法,来自定义bean的初始化和摧毁方法

public interface InitializingBean {
   void afterPropertiesSet() throws Exception;
}
public interface DisposableBean {
   void destroy() throws Exception;
}

在 创建bean的过程中,完成方法的注入,区分xml配置与接口实现。

initMethod 方法的注入与执行

@Override
   protected Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) {
       Object bean = null;
       try {
           bean = createBeanInstance(beanDefinition, beanName, args);
           // 注入属性
           applyPropertyValues(beanName, bean, beanDefinition);
           // 提供给外部的扩展包装,执行 Bean 的初始化方法和 BeanPostProcessor 的前置和后置处理方法
           bean = initializeBean(beanName, bean, beanDefinition);
       } catch (Exception e) {
           throw new RuntimeException("bean create error!", e);
       }
       // 注册实现了 DisposableBean 接口的 Bean 对象
       registerDisposableBeanIfNecessary(beanName, bean, beanDefinition);
       registerSingleton(beanName, bean);
       return bean;
   }
private Object initializeBean(String beanName, Object bean, BeanDefinition beanDefinition) throws BeansException {
       // 1. 执行 BeanPostProcess before 操作
       Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);
       try {
           // 执行bean初始化方法
           invokeInitMethods(beanName,wrappedBean,beanDefinition);
       }catch (Exception e){
           throw new BeansException("Invocation of init method of bean[" + beanName + "] failed", e);
       }
       // 2. 执行 BeanPostProcess after 操作
       wrappedBean = applyBeanPostProcessorsAfterInitialization(bean,beanName);
       return wrappedBean;
   }
private void invokeInitMethods(String beanName, Object bean, BeanDefinition beanDefinition) throws Exception {
   // 如果是通过接口实现,直接使用接口提供的方法    
   if (bean instanceof InitializingBean) {
           ((InitializingBean) bean).afterPropertiesSet();
       }
   // 通过xml配置,获取方法执行
       String initMethodName = beanDefinition.getInitMethodName();
       if (StrUtil.isNotEmpty(initMethodName)) {
           Method method = beanDefinition.getBeanClass().getMethod(initMethodName);
           // getMethod 已经做了非空判断
           if (null == method) {
               throw new BeansException("Could not find an init method named '" + initMethodName + "' on bean with name '" + beanName + "'");
           }
           method.invoke(bean);
       }
   }

destroyMethod 方法的注入与执行

提供一个适配器、来完成xml和接口的适配处理。处理逻辑基本与 init方法相似

/**
* bean 摧毁适配器
* @author huangle
* @date 2023/3/7 10:26
*/
public class DisposableBeanAdapter implements DisposableBean {
   /**
    * bean名字
    */
   private final String beanName;
   /**
    * bean
    */
   private final Object bean;
   /**
    * 销毁方法名称
    */
   private String destroyMethodName;
   public DisposableBeanAdapter(String beanName, Object bean, BeanDefinition beanDefinition) {
       this.beanName = beanName;
       this.bean = bean;
       this.destroyMethodName = beanDefinition.getDestoryMethodName();
   }
   @Override
   public void destroy() throws Exception {
       // 1. 实现 DisposableBean 接口,完成摧毁扩展
       if (bean instanceof DisposableBean) {
           ((DisposableBean) bean).destroy();
       }
       // 2. 通过xml配置 配置 destroy 方法 实现
       if (StrUtil.isNotEmpty(destroyMethodName) &amp;&amp; !(bean instanceof DisposableBean &amp;&amp; "destory".equals(destroyMethodName))) {
           Method destroyMethod = bean.getClass().getMethod(destroyMethodName);
           if (null == destroyMethod) {
               throw new BeansException("Couldn't find a destroy method named '" + destroyMethodName + "' on bean with name '" + beanName + "'");
           }
           destroyMethod.invoke(bean);
       }
   }
}

测试

userDao 通过xml配置初始化和摧毁方法,userService 通过继承接口来实现方法。

<?xml version="1.0" encoding="UTF-8"?>
<beans>
   <bean id="userDao" class="cn.anoxia.springframework.beans.factory.support.UserDao" init-method="initMethod" destroy-method="destroyMethod"/>
   <bean id="userService" class="cn.anoxia.springframework.beans.factory.support.UserService">
       <property name="name" value="Anoxia"/>
       <property name="nickname" value="迪迦"/>
       <property name="userDao" ref="userDao"/>
   </bean>
<!--    <bean id="myBeanPostProcecssor" class="cn.anoxia.springframework.beans.factory.support.MyBeanPostProcecssor"/>-->
<!--    <bean id="myFactoryPostProcessor" class="cn.anoxia.springframework.beans.factory.support.MyBeanFactoryPostProcessor"/>-->
</beans>
public class UserService implements InitializingBean, DisposableBean{
   @Override
   public void destroy() throws Exception {
       System.out.println("userService执行:destroy 方法");
   }
   @Override
   public void afterPropertiesSet() throws Exception {
       System.out.println("userService执行:init 方法");
   }
}

测试结果

如何实现bean初始化摧毁方法的注入

来源:https://juejin.cn/post/7224509927914078266

标签:bean,初始化,摧毁,方法注入
0
投稿

猜你喜欢

  • java实现斗地主游戏

    2022-02-18 14:06:26
  • java实现小i机器人api接口调用示例

    2023-02-05 00:09:15
  • SpringMVC使用MultipartFile实现文件上传

    2021-07-01 03:50:22
  • 玩转Android之Drawable的使用

    2023-07-01 22:42:46
  • Java网络编程之TCP通信完整代码示例

    2022-10-18 21:42:57
  • Java语法基础之循环结构语句详解

    2023-09-06 21:37:28
  • 详解Java使用JMH进行基准性能测试

    2021-08-01 12:22:32
  • Java+Nginx实现POP、IMAP、SMTP邮箱代理服务

    2023-11-26 10:31:47
  • Java Character类的详解

    2022-09-20 00:55:01
  • Java接口RandomAccess全面了解

    2023-09-11 19:05:29
  • IDEA中设置代码自动提示为Alt+/的具体做法

    2022-07-06 14:58:32
  • Java使用TCP套接字实现多人聊天功能详解

    2023-12-16 15:42:40
  • Android实现H5与Native交互的两种方式

    2023-01-01 05:35:42
  • 详解java中的static关键字

    2023-09-24 01:44:12
  • Android自定义gridView仿头条频道拖动管理功能

    2022-09-08 00:11:41
  • java开发MVC三层架构上再加一层Manager层原理详解

    2023-06-14 06:10:51
  • Unity3D运行报DllNotFoundException错误的解决方案

    2021-09-13 00:22:35
  • C# 中AutoMapper的使用方法

    2023-04-06 13:17:04
  • C#实现的24点游戏实例详解

    2023-03-01 16:38:51
  • Android Flutter实现GIF动画效果的方法详解

    2023-02-06 02:46:37
  • asp之家 软件编程 m.aspxhome.com