1. InitializingBean.afterPropertiesSet()
Spring中InitializingBean接口類為bean提供了定義初始化方法的方式,它僅僅包含一個方法:afterPropertiesSet()。
Bean實現這個接口,在afterPropertiesSet()中編寫初始化代碼:
public class EventEngineImpl implements EventEngine, InitializingBean { private static final Map<String, List<SubscribeRule>> EVENT_RULE_MAP = new HashMap<String, List<SubscribeRule>>(); /** * 規則列表 */ protected List<SubscribeRule> listEventRule; public void publishEvent(Event event) { ... } public void afterPropertiesSet() throws Exception { ... } public void setListEventRule(List<SubscribeRule> listEventRule) { this.listEventRule = listEventRule; } }
在xml配置文件中並不需要對bean進行特殊的配置,Spring在在配置文件完成該bean的所有賦值后,會檢查該bean是否實現了InitializingBean接口,如果實現就調用bean的afterPropertiesSet方法。
2. init-method配置
Spring雖然可以通過InitializingBean完成一個bean初始化后調用這個bean自定義方法,但是這種方式要求bean實現InitializingBean接口。一但bean實現了InitializingBean接口,那么這個bean的代碼就和Spring耦合到一起了。可以使用Spring提供的init-method的功能來執行一個bean自定義的初始化方法。
以下代碼中,類MonitorKafka不實現任何Spring的接口,定義一個沒有參數的方法monitorKafkaMsg()。
public class MonitorKafka { private String topic; public MonitorKafka() { } public void monitorKafkaMsg() { ... } protected void destroy() { try { if (null != consumerConnector) { consumerConnector.shutdown(); logger.debug("[kafka通用組件]停止消費線程組"); } if (null != executor) { executor.shutdownNow(); logger.debug("[kafka通用組件]停止線程池"); } } catch (RuntimeException e) { logger.error("[kafka通用組件]停止消費線程或停止線程池組異常.{}", e); } } public void setTopic(String topic) { this.topic = topic; } public String getTopic() { return topic; } }
<bean id="monitorPaymentKafka" class="com.xxx.xxx.kafka.MonitorKafka" scope="singleton" init-method="monitorKafkaMsg" destroy-method="destroy"> <property name="topic" value="test" /> </bean>
注:destroy-method是該bean銷毀前調用指定的方法。
init-method配置中的monitorKafkaMsg()方法將會在該bean初始化完成后被調用,Spring要求init-method是一個無參數的方法,否則會拋出異常,Spring將中止這個Bean的后續處理,並且拋出一個 org.springframework.beans.factory.BeanCreationException異常。
總結:
1. InitializingBean和init-method可以一起使用,Spring會先處理InitializingBean再處理init-method。init-method是通過反射執行的,而afterPropertiesSet是直接執行的,所以 afterPropertiesSet的執行效率比init-method要高,不過init-method消除了bean對Spring依賴,推薦使用init-method。
2. 如果一個bean被定義為非單例的,那么afterPropertiesSet和init-method在bean的每一個實例被創建時都會執行。單例bean的afterPropertiesSet和init-method只在bean第一次被實例時調用一次。一般情況下afterPropertiesSet和init-method都應用在單例的bean上。
3. @PostConstruct和@PreDestory可以通過在類方法上注解方式實現類似的功能。