SpringBoot 鉤子接口的實(shí)現(xiàn)代碼
Aware 接口族
Aware 意為感知,實(shí)現(xiàn) Aware 接口并重寫其方法,可以從上下文中獲取當(dāng)前的運(yùn)行環(huán)境
常見的 aware 接口
- BeanNameAware
- BeanFactoryAware
- BeanClassLoaderAware
- ApplicationContextAware
使用
@Component
@ToString
public class TestService implements BeanNameAware, BeanClassLoaderAware {
private String beanName;
private ClassLoader classLoader;
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
@Override
public void setBeanName(String name) {
this.beanName= name;
}
}
InitializingBean
InitializingBean 接口用于在 Bean 的初始化階段執(zhí)行自定義的操作,類型功能的還有 DisposableBean
使用
@Component
public class TestBean implements InitializingBean, DisposableBean {
// bean 設(shè)置完屬性之后調(diào)用
@Override
public void afterPropertiesSet() throws Exception {
// 初始化操作
System.out.println("TestBean init");
}
// 銷毀之后調(diào)用
@Override
public void destroy() throws Exception {
// 釋放資源
System.out.println("TestBean destroy");
}
}
BeanPostProcessor
BeanPostProcessor,Bean 的后置處理器,與 InitializingBean 不同的是,BeanPostProcessor 對所有 Bean 生效
使用
@Component
public class TestPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Bean 初始化前");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Bean 初始化后");
return bean;
}
}
BeanPostProcessor 使用場景非常多,可以獲取正在初始化的 Bean 對象,然后依據(jù)該 Bean 對象做一些定制化的操作,如:判斷該 Bean 是否為某個特定對象、獲取 Bean 的注解元數(shù)據(jù)等
Spring 內(nèi)置了非常多的 BeanPostProcessor ,以此來完善自身功能
BeanFactoryPostProcessor
BeanFactoryPostProcessor 是 Bean 工廠的后置處理器,一般用來修改上下文中的 BeanDefinition
使用
@Component
public class TestFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("所有 BeanDefinition 已被加載,但還未實(shí)例化 Bean");
// 動態(tài)添加 BeanDefinition
//轉(zhuǎn)換為子類 DefaultListableBeanFactory
DefaultListableBeanFactory defaultBeanFactory =
(DefaultListableBeanFactory) beanFactory;
//new 一個 beanDefinition對象
GenericBeanDefinition b = new GenericBeanDefinition();
b.setBeanClass(Testbean.class);
//添加一個 beanDefinition 對象
defaultBeanFactory.registerBeanDefinition("testBean", b);
// 動態(tài)獲取 BeanDefinition
Object o = defaultBeanFactory.getBean("testBean")
}
}
BeanDefinition 包含了 Spring 實(shí)例化一個 Bean 的所需的信息
ImportSelector
ImportSelector 可以動態(tài)的返回需要被容器管理的類,一般用來返回外部的配置類
public class TestImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
// AnnotationMetadata 存儲注解元數(shù)據(jù)信息
// 可以動態(tài)的返回需要被容器管理的類名稱
if (importingClassMetadata.hasAnnotation("")) {
// 判斷是否包含某個注解
}
// TestBean 加入到 Spring 容器中
return new String[]{"com.example.pojo.TestBean"};
}
}
在標(biāo)注 @Configuration 注解的類中,通過 @Import 導(dǎo)入 ImportSelector 來使之生效
@Configuration
@Import(TestImportSelector.class)
public class TestConfig {
}
ImportBeanDefinitionRegistrar
ImportBeanDefinitionRegistrar 也是配合 @Import 使用,可直接將 Bean 注冊到容器中
使用
public class TestRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
GenericBeanDefinition b = new GenericBeanDefinition();
b.setBeanClass(NotScanBean.class);
b.setLazyInit(true);
// 注冊到容器中
registry.registerBeanDefinition(NotScanBean.class.getName(), b);
}
}
FactoryBean
FactoryBean 為創(chuàng)建 Bean 提供了更加靈活的方式,常用于用于創(chuàng)建一類 Bean
Bean 實(shí)現(xiàn) FactoryBean 后,通過 getBean(String BeanName) 獲取到的 Bean 對象并不是 FactoryBean 的實(shí)現(xiàn)類對象,而是這個實(shí)現(xiàn)類中的 getObject() 方法返回的對象,在 BeanName 之前加上 &,可以獲取 FactoryBean 的實(shí)現(xiàn)類對象
使用
@Component
public class TestFactoryBean implements FactoryBean<TestBean> {
@Override
public TestBean getObject() throws Exception {
// 對 Bean 進(jìn)行配置
// 如代理、修飾等
return new TestBean();
}
@Override
public Class<?> getObjectType() {
return null;
}
}
ApplicationListener
ApplicationListener 是 Spring 實(shí)現(xiàn)事件機(jī)制的核心接口,屬于觀察者設(shè)計模式
ApplicationContext 可以發(fā)布 ApplicationEvent 事件,之后所有的 ApplicationListener 會被回調(diào)
自定義 ApplicationEvent
public class TestApplicationEvent extends ApplicationEvent {
public TestApplicationEvent(Object source) {
super(source);
}
public void hello(){
System.out.println("Hello Word!");
}
}
自定義 ApplicationListener
@Component
public class TestApplicationListener implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof TestApplicationEvent) {
TestApplicationEvent testApplicationEvent = (TestApplicationEvent) event;
testApplicationEvent.hello();
}
}
}
通過注入 ApplicationContext 或?qū)崿F(xiàn) ApplicationContextAware 接口,獲取 ApplicationContext 對象,發(fā)布 ApplicationEvent
@SpringBootTest
class DemoApplicationTests {
@Autowired
ApplicationContext applicationContext;
@Test
public void test() {
applicationContext.publishEvent(new TestApplicationEvent(new DemoApplication()));
}
}
// Hello Word!
ApplicationRunner
SpringBoot 應(yīng)用啟動成功會 callRunners 方法,所有 ApplicationRunner 實(shí)現(xiàn)類都會被回調(diào)
實(shí)現(xiàn) AppilcationRunner,ApplicationArguments 類型用來接收啟動參數(shù)
@Component
public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("原始參數(shù):" + Arrays.asList(args.getSourceArgs()));
Set<String> keys = args.getOptionNames();
for (String key : keys) {
System.out.println("解析后的 key: [" + key + "] value: " + args.getOptionValues(key));
}
System.out.println("無 OptionName 的參數(shù): " + args.getNonOptionArgs());
}
}
// 例:啟動參數(shù) --a=1 --b c
// 打印 =>
// 原始參數(shù):[--a=1, --b, c]
// 解析后的 key: [a] value: [1]
// 解析后的 key: [b] value: []
// 無 OptionName 的參數(shù): [c]
CommandLineRunner 和 ApplicationRunner 類似,但是只能獲得沒有經(jīng)過解析的原始參數(shù)
到此這篇關(guān)于SpringBoot 鉤子接口的實(shí)現(xiàn)代碼的文章就介紹到這了,更多相關(guān)SpringBoot 鉤子接口內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot實(shí)現(xiàn)異步調(diào)用的方法示例
本文介紹了在Java的SpringBoot中實(shí)現(xiàn)異步請求和異步調(diào)用的幾種方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-01-01
簡單了解JAVA public class與class區(qū)別
這篇文章主要介紹了簡單了解JAVA public class與class區(qū)別,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-03-03
使用java實(shí)現(xiàn)百萬級別數(shù)據(jù)導(dǎo)出excel的三種方式
這篇文章主要介紹了使用java實(shí)現(xiàn)百萬級別數(shù)據(jù)導(dǎo)出excel的三種方式,有些業(yè)務(wù)系統(tǒng)可能動輒涉及到百萬上千萬的數(shù)據(jù),用正常的方法效率就變得很低,今天我們來看看這幾種實(shí)現(xiàn)思路2023-03-03
IDEA提示內(nèi)存不足low memory的錯誤解決
運(yùn)行項(xiàng)目變得很卡,這種情況比較能直觀感受出來,Idea內(nèi)存指示器,則需要設(shè)置才能看到,本文主要介紹了IDEA提示內(nèi)存不足low memory的錯誤解決,具有一定的參考價值,感興趣的可以了解一下2024-03-03
IntelliJ IDEA版Postman強(qiáng)大功能介紹
這篇文章主要為大家介紹了IDEA版Postman的強(qiáng)大功能介紹,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
java隨機(jī)生成一個名字和對應(yīng)拼音的方法
這篇文章主要介紹了java隨機(jī)生成一個名字和對應(yīng)拼音的方法,涉及java針對數(shù)組及隨機(jī)數(shù)操作的相關(guān)技巧,需要的朋友可以參考下2015-07-07

