如何实现bean初始化摧毁方法的注入
实现 bean 初始化、摧毁方法的配置与处理
spring支持我们自定义 bean 的初始化方法和摧毁方法。配置方式可以通过 xml 的 init-method
和 destory-method
配置,或者实现 InitializingBean
、DisposableBean
接口,来完成自定义的初始化和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) && !(bean instanceof DisposableBean && "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初始化摧毁方法的注入的详细内容,更多关于bean初始化摧毁方法注入的资料请关注脚本之家其它相关文章!
相关文章
解决java 分割字符串成数组时,小圆点不能直接进行分割的问题
这篇文章主要介绍了解决java 分割字符串成数组时,小圆点不能直接进行分割的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧2020-12-12springboot自动扫描添加的BeanDefinition源码实例详解
这篇文章主要给大家介绍了关于springboot自动扫描添加的BeanDefinition的相关资料,文中通过实例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下2022-02-02Java Servlet响应httpServletResponse过程详解
HttpServletResponse是处理http响应的对象,调用该对象的方法,设置到对象属性的内容,tomcat最终会组织为http响应报文2022-02-02Springboot如何获取上下文ApplicationContext
这篇文章主要介绍了Springboot如何获取上下文ApplicationContext,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2021-11-11SpringBoot配置文件、多环境配置、读取配置的4种实现方式
SpringBoot支持多种配置文件位置和格式,其中application.properties和application.yml是默认加载的文件,配置文件可以根据环境通过spring.profiles.active属性进行区分,命令行参数具有最高优先级,可覆盖其他所有配置2024-09-09
最新评论