SpringBoot如何实现钩子接口

网友投稿 236 2024-02-03


SpringBoot如何实现钩子接口

本文主要介绍"SpringBoot怎么实现钩子接口",希望能够解决您遇到有关问题,下面我们一起来看这篇 "SpringBoot怎么实现钩子接口" 文章。

Aware 接口族

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

常见的 aware 接口

BeanNameAwareBeanFactoryAwareBeanClassLoaderAwareApplicationContextAware

使用

@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

使用

@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 生效

使用

@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

使用

@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 可以动态的返回需要被容器管理的类,一般用来返回外部的配置类

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 来使之生效

@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 为创建 Bean 提供了更加灵活的方式,常用于用于创建一类 Bean

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

使用

@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

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 或实现 ApplicationContextAware 接口,获取 ApplicationContext 对象,发布 ApplicationEvent

@SpringBootTest class DemoApplicationTests {     @Autowired     ApplicationContext applicationContext;     @Test     public void test() {         applicationContext.publishEvent(new TestApplicationEvent(new DemoApplication()));     } } // Hello Word!

ApplicationRunner

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

@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 类似,但是只能获得没有经过解析的原始参数

编程技术 和 程序设计

jQuery如何实现点击出现爱心特效:本文主要介绍"jQuery怎么实现点击出现爱心特效",希望能够解决您遇到有关问题,下面我们一起来看这篇 "jQuery怎么实现点击出现爱心特效" 文章。具体内容如下代码:<!DOCTYPE htm ...


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java中怎么利用Swagger配置扫描接口
下一篇:python requests 库请求带有文件参数的接口实例
相关文章

 发表评论

暂时没有评论,来抢沙发吧~