服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - SpringBoot 钩子接口的实现代码

SpringBoot 钩子接口的实现代码

2021-11-29 12:04CadeCode Java教程

本文主要介绍了SpringBoot 钩子接口,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

Aware 接口族

Aware 意为感知,实现 Aware 接口并重写其方法,可以从上下文中获取当前的运行环境

常见的 aware 接口

  • BeanNameAware
  • BeanFactoryAware
  • BeanClassLoaderAware
  • ApplicationContextAware

使用

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@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 的初始化阶段执行自定义的操作,类型功能的还有 DisposableBean

使用

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Component
public class TestBean implements InitializingBean, DisposableBean {
 
    // bean 设置完属性之后调用
    @Override
    public void afterPropertiesSet() throws Exception {
        // 初始化操作
        System.out.println("TestBean init");
    }
 
    // 销毁之后调用
    @Override
    public void destroy() throws Exception {
        // 释放资源
        System.out.println("TestBean destroy");
    }
}

BeanPostProcessor

BeanPostProcessor,Bean 的后置处理器,与 InitializingBean 不同的是,BeanPostProcessor 对所有 Bean 生效

使用

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@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 对象,然后依据该 Bean 对象做一些定制化的操作,如:判断该 Bean 是否为某个特定对象、获取 Bean 的注解元数据等

Spring 内置了非常多的 BeanPostProcessor ,以此来完善自身功能

BeanFactoryPostProcessor

BeanFactoryPostProcessor 是 Bean 工厂的后置处理器,一般用来修改上下文中的 BeanDefinition

使用

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Component
public class TestFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("所有 BeanDefinition 已被加载,但还未实例化 Bean");
        
        // 动态添加 BeanDefinition
        //转换为子类 DefaultListableBeanFactory
        DefaultListableBeanFactory defaultBeanFactory =
            (DefaultListableBeanFactory) beanFactory;
        //new 一个 beanDefinition对象
        GenericBeanDefinition b = new GenericBeanDefinition();
        b.setBeanClass(Testbean.class);
        //添加一个 beanDefinition 对象
        defaultBeanFactory.registerBeanDefinition("testBean", b);
        
        // 动态获取 BeanDefinition
  Object o = defaultBeanFactory.getBean("testBean")
    }
}

BeanDefinition 包含了 Spring 实例化一个 Bean 的所需的信息

ImportSelector

ImportSelector 可以动态的返回需要被容器管理的类,一般用来返回外部的配置类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class TestImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        
        // AnnotationMetadata 存储注解元数据信息
        // 可以动态的返回需要被容器管理的类名称
        if (importingClassMetadata.hasAnnotation("")) {
            // 判断是否包含某个注解
        }
        
        // TestBean 加入到 Spring 容器中
        return new String[]{"com.example.pojo.TestBean"};
    }
}

在标注 @Configuration 注解的类中,通过 @Import 导入 ImportSelector 来使之生效

?
1
2
3
4
@Configuration
@Import(TestImportSelector.class)
public class TestConfig {
}

ImportBeanDefinitionRegistrar

ImportBeanDefinitionRegistrar 也是配合 @Import 使用,可直接将 Bean 注册到容器中

使用

?
1
2
3
4
5
6
7
8
9
10
11
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 为创建 Bean 提供了更加灵活的方式,常用于用于创建一类 Bean

Bean 实现 FactoryBean 后,通过 getBean(String BeanName) 获取到的 Bean 对象并不是 FactoryBean 的实现类对象,而是这个实现类中的 getObject() 方法返回的对象,在 BeanName 之前加上 &,可以获取 FactoryBean 的实现类对象

使用

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Component
public class TestFactoryBean implements FactoryBean<TestBean> {
    @Override
    public TestBean getObject() throws Exception {
 
        // 对 Bean 进行配置
        // 如代理、修饰等
 
        return new TestBean();
    }
 
    @Override
    public Class<?> getObjectType() {
        return null;
    }
}

ApplicationListener

ApplicationListener 是 Spring 实现事件机制的核心接口,属于观察者设计模式

ApplicationContext 可以发布 ApplicationEvent 事件,之后所有的 ApplicationListener 会被回调

自定义 ApplicationEvent

?
1
2
3
4
5
6
7
8
9
10
public class TestApplicationEvent extends ApplicationEvent {
 
    public TestApplicationEvent(Object source) {
        super(source);
    }
 
    public void hello(){
        System.out.println("Hello Word!");
    }
}

自定义 ApplicationListener

?
1
2
3
4
5
6
7
8
9
10
11
@Component
public class TestApplicationListener implements ApplicationListener {
 
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof TestApplicationEvent) {
            TestApplicationEvent testApplicationEvent = (TestApplicationEvent) event;
            testApplicationEvent.hello();
        }
    }
}

通过注入 ApplicationContext 或实现 ApplicationContextAware 接口,获取 ApplicationContext 对象,发布 ApplicationEvent

?
1
2
3
4
5
6
7
8
9
10
11
12
@SpringBootTest
class DemoApplicationTests {
 
    @Autowired
    ApplicationContext applicationContext;
 
    @Test
    public void test() {
        applicationContext.publishEvent(new TestApplicationEvent(new DemoApplication()));
    }
}
// Hello Word!

ApplicationRunner

SpringBoot 应用启动成功会 callRunners 方法,所有 ApplicationRunner 实现类都会被回调

实现 AppilcationRunner,ApplicationArguments 类型用来接收启动参数

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Component
public class MyApplicationRunner implements ApplicationRunner {
 
    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("原始参数:" + 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 的参数: " + args.getNonOptionArgs());
    }
}
// 例:启动参数 --a=1 --b c
// 打印 =>
// 原始参数:[--a=1, --b, c]
// 解析后的 key: [a]  value: [1]
// 解析后的 key: [b]  value: []
// 无 OptionName 的参数: [c]

CommandLineRunner 和 ApplicationRunner 类似,但是只能获得没有经过解析的原始参数

到此这篇关于SpringBoot 钩子接口的实现代码的文章就介绍到这了,更多相关SpringBoot 钩子接口内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://juejin.cn/post/6998887774614978573

延伸 · 阅读

精彩推荐
  • Java教程20个非常实用的Java程序代码片段

    20个非常实用的Java程序代码片段

    这篇文章主要为大家分享了20个非常实用的Java程序片段,对java开发项目有所帮助,感兴趣的小伙伴们可以参考一下 ...

    lijiao5352020-04-06
  • Java教程Java BufferWriter写文件写不进去或缺失数据的解决

    Java BufferWriter写文件写不进去或缺失数据的解决

    这篇文章主要介绍了Java BufferWriter写文件写不进去或缺失数据的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望...

    spcoder14552021-10-18
  • Java教程Java实现抢红包功能

    Java实现抢红包功能

    这篇文章主要为大家详细介绍了Java实现抢红包功能,采用多线程模拟多人同时抢红包,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙...

    littleschemer13532021-05-16
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    这篇文章主要介绍了Java使用SAX解析xml的示例,帮助大家更好的理解和学习使用Java,感兴趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程Java8中Stream使用的一个注意事项

    Java8中Stream使用的一个注意事项

    最近在工作中发现了对于集合操作转换的神器,java8新特性 stream,但在使用中遇到了一个非常重要的注意点,所以这篇文章主要给大家介绍了关于Java8中S...

    阿杜7482021-02-04
  • Java教程小米推送Java代码

    小米推送Java代码

    今天小编就为大家分享一篇关于小米推送Java代码,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧...

    富贵稳中求8032021-07-12
  • Java教程升级IDEA后Lombok不能使用的解决方法

    升级IDEA后Lombok不能使用的解决方法

    最近看到提示IDEA提示升级,寻思已经有好久没有升过级了。升级完毕重启之后,突然发现好多错误,本文就来介绍一下如何解决,感兴趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程xml与Java对象的转换详解

    xml与Java对象的转换详解

    这篇文章主要介绍了xml与Java对象的转换详解的相关资料,需要的朋友可以参考下...

    Java教程网2942020-09-17