发现公司的项目,每次启动时候,如果有大量的mq消费者,会优先消费mq。但是这样会有隐患,比如如果有大量的mq堆积,每次项目启动时候会先去消费而导致重启很慢;或者启动失败,但是mq却消费成功了的问题。
这几天一直在尝试解决这个问题。考虑了懒加载的方式、使用ApplicationRunner想要启动成功后再去加载,以及通过springboot注解Condition的方式,ConditionalOnClass以及ConditionalOnBean的方式。发现都不行。由于项目里面使用的是rocketmq-spring-boot的jar包,里面是通过@import 的方式在spring启动时候作为组件加载进去的,在启动时候他们是通过mq的监听来实现的加载。想要自己去实现,但是考虑实际情况,还是有些问题。
package com.gwm.marketing.init; import com.gwm.marketing.message.community.AuditMessageConsumer; import com.gwm.marketing.message.community.PublishAprvalMessageConsumer; import com.gwm.marketing.message.community.SyncUserMessageConsumer; import com.gwm.marketing.message.community.VideoMqConsumer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanDefinitionStoreException; import org.springframework.beans.factory.SmartInitializingSingleton; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.*; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.boot.autoconfigure.condition.ConditionOutcome; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.SpringBootCondition; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.*; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.core.type.AnnotatedTypeMetadata; import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.util.Arrays; /** * @author fanht * @descrpiton 实现Runner,满足应用刚好启动后需要立马被执行的需求 * @date 2022/7/6 14:45:48 * @versio 1.0 */ @Component public class InitRunner implements ApplicationRunner, SmartInitializingSingleton, ConfigurationCondition { private Logger logger = LoggerFactory.getLogger(this.getClass()); @Resource private DefaultListableBeanFactory defaultListableBeanFactory; boolean bl = false;
@Override public void run(ApplicationArguments args) throws Exception { logger.info("=====================mq===============init==============start"); bl = true; try { if(bl){ BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(PublishAprvalMessageConsumerTest.class); defaultListableBeanFactory.registerBeanDefinition(PublishAprvalMessageConsumerTest.class.getName(), builder.getBeanDefinition()); } } catch (BeanDefinitionStoreException e) { logger.error("======init error=========",e); } logger.info("=====================mq===============init==============success"); } @Override public void afterSingletonsInstantiated() { System.out.println("================afterSingletonsInstantiated=============="); } @Override public ConfigurationPhase getConfigurationPhase() { return null; } @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { /* ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); boolean exist = !beanFactory.getBeansOfType(InitRunner.class).isEmpty(); System.out.println("==========是否存在InitRunner======" + exist); return exist;*/ return bl; } //@Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { /* AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(PublishAprvalMessageConsumerTest.class).getBeanDefinition(); registry.registerBeanDefinition("publishAprvalMessageConsumerTest",beanDefinition);*/ } // @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { /* String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames(); Arrays.stream(beanDefinitionNames).forEach(m->{ if("publishAprvalMessageConsumerTest".equalsIgnoreCase(m)){ registerBean((DefaultListableBeanFactory) beanFactory,beanFactory.getType(m)); } });*/ } /*private void registerBean(DefaultListableBeanFactory defaultListableBeanFactory, Class cla) { BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(cla); //builder.setScope(BeanDefinition.SCOPE_SINGLETON); //builder.addConstructorArgValue(cla); builder.setLazyInit(true); defaultListableBeanFactory.registerBeanDefinition(cla.getName(), builder.getBeanDefinition()); }*/ }
试了上面的几种方式,没一种可以的。到底问题出在哪里呢?