您好,登錄后才能下訂單哦!
本文小編為大家詳細介紹“怎么實現bean初始化摧毀方法的注入”,內容詳細,步驟清晰,細節處理妥當,希望這篇“怎么實現bean初始化摧毀方法的注入”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
spring支持我們自定義 bean 的初始化方法和摧毀方法。配置方式可以通過 xml 的 init-method
和 destory-method
配置,或者實現 InitializingBean
、DisposableBean
接口,來完成自定義的初始化和bean的銷毀。 在項目開發過程中,相信最多看到的是 @PostConstruct
注解標識的方法來進行bean的初始化。
@PostConstruct 是 Spring Framework 提供的注解,可以用于在 Bean 實例化之后執行初始化操作
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配置與接口實現。
@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); } }
提供一個適配器、來完成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初始化摧毀方法的注入”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。