首页 > 其他分享 >springboot~ApplicationContextAware和Interceptor产生了真感情

springboot~ApplicationContextAware和Interceptor产生了真感情

时间:2023-08-18 10:34:47浏览次数:39  
标签:ApplicationContextAware applicationContext springboot record bean ttl new Interc

看着题目,有点一头污水吧,事实上,没有经历过,很难去说ApplicationContextAware在什么时候会用到,直接在一个bean对象里,你可以直接使用构造方法注入或者Autowired属性注入的方式来使用其它的bean对象,这在springboot里是非常自然的,也是天然支持的;但如果你的这个bean不是由spring ioc自动注入的,而是通过拦截器动态配置的,这时你使用@Autowired时,是无法获取到其它bean对象的;这时你需要使用ApplicationContextAware接口,再定义一个静态的ApplicationContext实例,在你的拦截器执行方法里使用它就可以了。【应该和拦截器里的动态代理有关】

一个kafka的ConsumerInterceptor实例

在这个例子中,我们通过ConsumerInterceptor实现了一个TTL的延时队列,当topic过期时,再通过KafkaTemplate将消息转发到其它队列里

  • DelayPublisher.publish发送延时topic的方法
	/**
	 * 发送延时消息
	 * @param message 消息体
	 * @param delaySecondTime 多个秒后过期
	 * @param delayTopic 过期后发送到的话题
	 */
	public void publish(String message, long delaySecondTime, String delayTopic) {
		ProducerRecord producerRecord = new ProducerRecord<>(topic, 0, System.currentTimeMillis(), delayTopic, message,
				new RecordHeaders().add(new RecordHeader("ttl", toBytes(delaySecondTime))));
		kafkaTemplate.send(producerRecord);
	}

  • ConsumerInterceptorTTL
/**
 * @author lind
 * @date 2023/8/18 8:33
 * @since 1.0.0
 */
@Component
public class ConsumerInterceptorTTL implements ConsumerInterceptor<String, String>, ApplicationContextAware {

	// 静态化的上下文,用于获取bean,因为ConsumerInterceptor是通过反射创建的,所以无法通过注入的方式获取bean
	private static ApplicationContext applicationContext;

	@Override
	public ConsumerRecords<String, String> onConsume(ConsumerRecords<String, String> records) {
		long now = System.currentTimeMillis();
		Map<TopicPartition, List<ConsumerRecord<String, String>>> newRecords = new HashMap<>();
		for (TopicPartition tp : records.partitions()) {
			List<ConsumerRecord<String, String>> tpRecords = records.records(tp);
			List<ConsumerRecord<String, String>> newTpRecords = new ArrayList<>();
			for (ConsumerRecord<String, String> record : tpRecords) {
				Headers headers = record.headers();
				long ttl = -1;
				for (Header header : headers) {
					if (header.key().equals("ttl")) {
						ttl = toLong(header.value());
					}
				}
				// 消息超时判定
				if (ttl > 0 && now - record.timestamp() < ttl * 1000) {
					// 可以放在死信队列中
					System.out.println("消息超时了,需要发到topic:" + record.key());
					KafkaTemplate kafkaTemplate = applicationContext.getBean(KafkaTemplate.class);
					kafkaTemplate.send(record.key(), record.value());
				}
				else { // 没有设置TTL,不需要超时判定
					newTpRecords.add(record);
				}

			}
			if (!newRecords.isEmpty()) {
				newRecords.put(tp, newTpRecords);
			}
		}
		return new ConsumerRecords<>(newRecords);
	}

	@Override
	public void onCommit(Map<TopicPartition, OffsetAndMetadata> offsets) {
		offsets.forEach((tp, offset) -> System.out.println(tp + ":" + offset.offset()));
	}

	@Override
	public void close() {
	}

	@Override
	public void configure(Map<String, ?> configs) {

	}

	// 它的时机是在KafkaListenerAnnotationBeanPostProcessor的postProcessAfterInitialization方法中,applicationContext应该定时成static,否则在实例对象中,它的值可能是空
	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	}

}
  • 配置文件中注入拦截器
spring:
  kafka:
    consumer:
      properties:
        interceptor.classes: com.example.ConsumerInterceptorTTL 

标签:ApplicationContextAware,applicationContext,springboot,record,bean,ttl,new,Interc
From: https://www.cnblogs.com/lori/p/17639745.html

相关文章

  • Springboot整合模版方法模式概念->原理优缺点->框架应用场景->企业级实战
    一、前言常见的设计模式有23种,我们不得不提到模板方法设计模式,这是一种在软件开发中广泛使用的行为型设计模式之一。它为我们提供了一种优雅的方式来定义算法的结构,并将算法的具体实现延迟到子类中!在本篇博客中,我们将深入探讨模板方法设计模式在SpringBoot中的应用。我们将从概念......
  • springboot 打包 时报错:The specified user settings file does not exist: F:\opt\
     解决方法:  ......
  • 【Spring boot】快速创建springboot项目
     1、文件-新建项目 2、选择spring填写信息 3、添加依赖包<后续可以在pom.xml中引入依赖包>  4、项目生成完成  ......
  • SpringBoot初体验
    1.何为SpringBoot简单理解:是集成于spring的优点继而简化spring配置SpringBoot简化了整个搭建与开发的过程当然,其通过集成大量的框架使得依赖包的版本冲突,以及引用的不稳定性等问题得到了很好的解决。2.springboot优势(1)可以创建独立的Spring应用程序,并且基于其Maven或Gradle插......
  • springboot综合案例综合案例第五课
    角色管理角色查询角色查询直接查询即可角色查询执行流程编写RoleMapper接口publicinterfaceRoleMapper{/***查询角色*/List<Role>findAll();}编写RoleServicepublicinterfaceRoleService{/***查询角色*@parampage......
  • 有关springboot的一些理解
    springboot概念springboot是spring项目的脚手架,其能够快速构建spring项目,不再需要一些对应用程序的xml文件配置,其自带许多硬件设备的驱动。其核心是约定大于配置理念,即减少人为配置,尽量采用默认的配置即可。例如,不同于单独的springMVC,其默认配置了包括tomcat服务器,视图解析器等......
  • SpringBoot+Mybatis-Plus+Mysql的保姆级搭建
    本文通过简单的示例代码和说明,让读者能够了解Mybatis-Plus+Mysql的简单使用必须说明的是,本文有部分内容是为了后续的微服务写的,所以如果只想用Mybatis-Plus的话,直接使用bank1项目即可 1.新建父项目,选用springinitializr即可,可以删除其他文件,仅仅留下pom文件当成父pom。修改......
  • SpringBoot操作前端传的Geojson进行空间查询
    SpringBoot操作前端传的Geojson进行空间查询项目说明:项目技术栈:SpringBoot+MybatisPlus+postgresql先上查询SQLSELECT*FROMdemoWHEREST_Intersects(geom,ST_GeomFromGeoJSON('放geojson类型数据'));表结构Controller层packagecom.itcy.postgresql.controller;importco......
  • RabbitMQ与SpringBoot 集成
    1、添加依赖<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency> 2、添加配置官方配置https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/h......
  • springboot集成cas
    CAS介绍CAS是CentralAuthenticationService的缩写,中央认证服务,一种独立开放指令协议。CAS是耶鲁大学(YaleUniversity)发起的一个开源项目,旨在为Web应用系统提供一种可靠的单点登录方法,CAS在2004年12月正式成为JA-SIG的一个项目。特点:开源的企业级单点登录解决方案......