溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

spring啟動(dòng)加載程序的幾種方法介紹

發(fā)布時(shí)間:2020-10-20 16:49:31 來源:腳本之家 閱讀:210 作者:OnMyWay--YAO 欄目:編程語言

關(guān)于在spring  容器初始化 bean 和銷毀前所做的操作定義方式有三種:

第一種:通過注解@PostConstruct 和 @PreDestroy 方法 實(shí)現(xiàn)初始化和銷毀bean之前進(jìn)行的操作

import javax.annotation.PostConstruct; 
import javax.annotation.PreDestroy; 
 
public class DataInitializer{  
 @PostConstruct 
 public void initMethod() throws Exception { 
  System.out.println("initMethod 被執(zhí)行"); 
 } 
 @PreDestroy 
 public void destroyMethod() throws Exception { 
  System.out.println("destroyMethod 被執(zhí)行"); 
 } 
} 

第二種是:通過 在xml中定義init-method 和  destory-method方法

public class DataInitializer{ 
 public void initMethod() throws Exception { 
  System.out.println("initMethod 被執(zhí)行"); 
 } 
 public void destroyMethod() throws Exception { 
  System.out.println("destroyMethod 被執(zhí)行"); 
 } 
} 

復(fù)制代碼 代碼如下:

<bean id="dataInitializer" class="com.somnus.demo.DataInitializer" init-method="initMethod" destory-method="destroyMethod"/> 

第三種是: 通過bean實(shí)現(xiàn)InitializingBean和 DisposableBean接口

import org.springframework.beans.factory.DisposableBean; 
 
public class DataInitializer implements InitializingBean,DisposableBean{ 
  
 @Override 
 public void afterPropertiesSet() throws Exception { 
  System.out.println("afterPropertiesSet 被執(zhí)行"); 
 } 
  
 @Override 
 public void destroy() throws Exception { 
  System.out.println("destroy 被執(zhí)行"); 
 } 
 
} 

 其中第一種和第二種是同一種形式,只不過一種xml配置,另外一種采用注解形式罷了,有很大區(qū)別的是第三種,如果同一個(gè)bean同時(shí)采用兩種方式初始化的時(shí)候執(zhí)行某個(gè)方法,首先在執(zhí)行順序上就會(huì)體現(xiàn)出來。

先執(zhí)行afterPropertiesSet(),后執(zhí)行initMethod()

這里我們看下源碼

這方式在spring中是怎么實(shí)現(xiàn)的?

通過查看spring的加載bean的源碼類(AbstractAutowireCapableBeanFactory)可看出其中奧妙

AbstractAutowireCapableBeanFactory類中的invokeInitMethods講解的非常清楚,源碼如下:

protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) 
  throws Throwable { 
 //判斷該bean是否實(shí)現(xiàn)了實(shí)現(xiàn)了InitializingBean接口,如果實(shí)現(xiàn)了InitializingBean接口,則只掉調(diào)用bean的afterPropertiesSet方法 
 boolean isInitializingBean = (bean instanceof InitializingBean); 
 if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { 
  if (logger.isDebugEnabled()) { 
   logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'"); 
  } 
  
  if (System.getSecurityManager() != null) { 
   try { 
    AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { 
     public Object run() throws Exception { 
      //直接調(diào)用afterPropertiesSet 
      ((InitializingBean) bean).afterPropertiesSet(); 
      return null; 
     } 
    },getAccessControlContext()); 
   } catch (PrivilegedActionException pae) { 
    throw pae.getException(); 
   } 
  }     
  else { 
   //直接調(diào)用afterPropertiesSet 
   ((InitializingBean) bean).afterPropertiesSet(); 
  } 
 } 
 if (mbd != null) { 
  String initMethodName = mbd.getInitMethodName(); 
  //判斷是否指定了init-method方法,如果指定了init-method方法,則再調(diào)用制定的init-method 
  if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && 
    !mbd.isExternallyManagedInitMethod(initMethodName)) { 
    //進(jìn)一步查看該方法的源碼,可以發(fā)現(xiàn)init-method方法中指定的方法是通過反射實(shí)現(xiàn) 
   invokeCustomInitMethod(beanName, bean, mbd); 
  } 
 } 

總結(jié):

1:spring為bean提供了兩種初始化bean的方式,實(shí)現(xiàn)InitializingBean接口,實(shí)現(xiàn)afterPropertiesSet方法,或者在配置文件中同過init-method指定,兩種方式可以同時(shí)使用

2:實(shí)現(xiàn)InitializingBean接口是直接調(diào)用afterPropertiesSet方法,比通過反射調(diào)用init-method指定的方法效率相對來說要高點(diǎn)。但是init-method方式消除了對spring的依賴

3:如果調(diào)用afterPropertiesSet方法時(shí)出錯(cuò),則不調(diào)用init-method指定的方法。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI