??簡介
??JSR-250規范為Bean初始化之后/銷毀之前方法指定了兩個注解:@PostConstruct和@PreDestroy,這兩個注解可以應用在方法級別上,@PostConstruct注釋方法在Bean實體化之后、應用注入之前呼叫,@PreDestroy注釋方法在Bean實體銷毀之前呼叫,
??@PostConstruct和@PreDestroy規范中要去較為嚴格,但Spring在實作時,并未完全按照其規范實作,在Spring中應用@PostConstruct和@PreDestroy這兩個注解,以實作約束為準即可,
??注意事項
??InitializingBean注意事項:
??① Bean必須實作InitializingBean介面,
??② Bean的afterPropertiesSet不能使用@PostConstruct注釋,
??init-method注意事項:
??① init-method指定屬性不能為空,
??② Bean不可以實作InitializingBean介面或Bean的init-method方法名不可以為afterPropertiesSet,
??③ Bean的init-method方法不能使用@PostConstruct注釋,
??@PostConstruct注意事項:
??① 可以應用于任何可見性的方法:public、package-protected、protected或private,
??② 不能注釋在InitializingBean.afterPropertiesSet()和init-method方法上,可能導致后兩者失效,
??演示示例
??@PostConstruct、InitializingBean和init-method都可以用作Bean初始化相關操作,示例將一起演示這三種方式,
??1) 建InitTestBean,用于進行初始化相關的測驗,
??① 實作InitializingBean介面,重寫afterPropertiesSet()方法,
??② 添加initMethod()方法,用于進行init-method的配置,
??③ 添加postConstructor()方法,用于@PostConstruct注解注釋,
package com.arhorchin.securitit.initbean;
import javax.annotation.PostConstruct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
/**
* @author Securitit.
* @note Bean初始化測驗.
*/
public class InitTestBean implements InitializingBean {
/**
* logger.
*/
private Logger logger = LoggerFactory.getLogger(InitTestBean.class);
@Override
public void afterPropertiesSet() throws Exception {
logger.info("呼叫InitializingBean的afterPropertiesSet方法.");
}
public void initMethod() throws Exception {
logger.info("呼叫init-method的initMethod方法.");
}
@PostConstruct
public void postConstructor() throws Exception {
logger.info("呼叫@PostConstruct注釋的方法.");
}
}
??2) 在Spring的組態檔中增加Bean宣告,并指定init-method屬性,
<bean class="com.arhorchin.securitit.initbean.InitTestBean" init-method="initMethod"></bean>
??3) 運行程式查看效果,可以看到如下的輸出,
2020-12-17 14:42:12 INFO [c.a.s.i.InitTestBean] 呼叫@PostConstruct注釋的方法.
2020-12-17 14:42:12 INFO [c.a.s.i.InitTestBean] 呼叫InitializingBean的afterPropertiesSet方法.
2020-12-17 14:42:12 INFO [c.a.s.i.InitTestBean] 呼叫init-method的initMethod方法.
??從運行結果可以看出:
??① @PostConstruct先于InitializingBean.afterPropertiesSet(),
??② InitializingBean.afterPropertiesSet()先于init-method的initMethod(),
??自定義注解示例
??@PostConstruct和@PreDestroy實作關鍵在于org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor,而InitDestroyAnnotationBeanPostProcessor允許通過setInitAnnotationType(...)和setDestroyAnnotationType(...)來自定義初始化和銷毀注解型別,
??1) 自定義注解@DefPostConstruct,用于進行演示,
package com.arhorchin.securitit.initbean;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author Securitit.
* @note 自定義初始化注解.
*/
@Documented
@Retention (RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface DefPostConstruct {
}
??2) 建DefApplicationContextAware,實作ApplicationContextAware,用于通過InitDestroyAnnotationBeanPostProcessor的setInitAnnotationType(...)和setDestroyAnnotationType(...)設定初始化和銷毀注解型別,
package com.arhorchin.securitit.initbean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
/**
* @author Securitit.
* @note 用于測驗自定義注解的ApplicationContextAware.
*/
public class DefApplicationContextAware implements ApplicationContextAware {
/**
* logger.
*/
private Logger logger = LoggerFactory.getLogger(DefApplicationContextAware.class);
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
InitDestroyAnnotationBeanPostProcessor initDestroy = null;
initDestroy = applicationContext.getBean(InitDestroyAnnotationBeanPostProcessor.class);
logger.info("BeanPostProcessor.postProcessBeforeInitialization呼叫.Bean名稱:" + initDestroy);
initDestroy.setInitAnnotationType(DefPostConstruct.class);
initDestroy.setDestroyAnnotationType(DefPreDestroy.class);
}
}
??3) 修改InitTestBean,用于進行初始化相關的測驗,
package com.arhorchin.securitit.initbean;
import javax.annotation.PostConstruct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
/**
* @author Securitit.
* @note Bean初始化測驗.
*/
public class InitTestBean implements InitializingBean {
/**
* logger.
*/
private Logger logger = LoggerFactory.getLogger(InitTestBean.class);
@Override
public void afterPropertiesSet() throws Exception {
logger.info("呼叫InitializingBean的afterPropertiesSet方法.");
}
public void initMethod() throws Exception {
logger.info("呼叫init-method的initMethod方法.");
}
@DefPostConstruct
public void postConstructor() throws Exception {
logger.info("呼叫@PostConstruct注釋的方法.");
}
}
??4) 在Spring的組態檔中增加Bean宣告,并指定init-method屬性,同時配置DefApplicationContextAware,
<!-- 配置 ApplicationContextAware -->
<bean
class="com.arhorchin.securitit.initbean.DefApplicationContextAware"></bean>
<!-- 配置 InitTestBean -->
<bean class="com.arhorchin.securitit.initbean.InitTestBean"
init-method="initMethod"></bean>
??5) 運行程式查看效果,可以看到如下的輸出,
2020-12-17 17:01:08 INFO [c.a.s.i.DefApplicationContextAware] ApplicationContextAware.setApplicationContext呼叫.Bean:org.springframework.context.annotation.CommonAnnotationBeanPostProcessor@3027f7ce
2020-12-17 17:01:08 INFO [c.a.s.i.InitTestBean] 呼叫@DefPostConstruct注釋的方法.
2020-12-17 17:01:08 INFO [c.a.s.i.InitTestBean] 呼叫InitializingBean的afterPropertiesSet方法.
2020-12-17 17:01:08 INFO [c.a.s.i.InitTestBean] 呼叫init-method的initMethod方法.
??可以看到,自定義注解同樣達到了與@PostConstruct注解相同的效果,
??總結
??本文對@PostConstruct的應用進行了演示,同時一并演示了InitializingBean和init-method,并通過示例驗證了三者之間的呼叫順序,充分了解這點,還是十分有用的,
??原始碼決議基于spring-framework-5.0.5.RELEASE版本原始碼,
??若文中存在錯誤和不足,歡迎指正!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/237628.html
標籤:java
上一篇:【每日一題】力扣48.旋轉影像
