Hutool中SpringUtil中的一个坑-所有路由消失

问题场景

Spring boot 2.7.18
使用Hutool文档中使用方法

@ComponentScan(basePackages={"cn.hutool.extra.spring"})
@Import(cn.hutool.extra.spring.SpringUtil.class)

在主入口定义,会导致路由全部消失,接口访问404。

解决方案

使用提供的@EnableSpringUtil注解或者新建个配置类,将两个注解放到上面。

原因分析

ComponentScan 注解 与 @Import 注解

@ComponentScan 用于自动检测和注册带有特定注解的类为bean。这些注解通常包括但不限于 @Component , @Service , @Repository , 和 @Controller 。当一个配置类上使用了 @ComponentScan ,Spring会扫描指定的包及其子包,并将所有带有上述注解的类作为bean注册到IoC容器中。

  • @ComponentScan主要用于自动发现和注册组件
  • @Impoert适用于导入特定的配置类和静态bean定义,便于模块化配置

怀疑是@SpringApplication中的@ComponentScan同主入口的@ComponetScan相冲突

BeanFactoryPostProcessor

允许开发者在Spring IoC容器初始化之前对BeanFactory进行修改,是最早要执行的方法。该接口只有一个方法需要实现

public interface BeanFactoryPostProcessor {
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

这个函数允许访问并修改BeanFactory的内容,这个方法调用发生在所有bean实例化之前,可以进行配置。

ApplicationContextAware

使一个类能够获得整个Spring应用上下文(ApplicationContext)的引用。通常,当一个类实现了ApplicationContextAware接口后,Spring容器会在初始化该类的实例时自动调用一个回调方法,将当前的ApplicationContext实例注入给该类。

SpringUtil的代码

通过实现上面两个BeanFactoryPostProcessorApplicationContextAware的接口,可以实现Util方法,不用实例化,直接调用静态方法

@Component
public class SpringUtil implements BeanFactoryPostProcessor, ApplicationContextAware {

	/**
	 * "@PostConstruct"注解标记的类中,由于ApplicationContext还未加载,导致空指针<br>
	 * 因此实现BeanFactoryPostProcessor注入ConfigurableListableBeanFactory实现bean的操作
	 */
	private static ConfigurableListableBeanFactory beanFactory;
	/**
	 * Spring应用上下文环境
	 */
	private static ApplicationContext applicationContext;

	@SuppressWarnings("NullableProblems")
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		SpringUtil.beanFactory = beanFactory;
	}

	@SuppressWarnings("NullableProblems")
	@Override
	public void setApplicationContext(ApplicationContext applicationContext) {
		SpringUtil.applicationContext = applicationContext;
	}

	/**
	 * 获取{@link ApplicationContext}
	 *
	 * @return {@link ApplicationContext}
	 */
	public static ApplicationContext getApplicationContext() {
		return applicationContext;
	}

	/**
	 * 获取{@link ListableBeanFactory},可能为{@link ConfigurableListableBeanFactory} 或 {@link ApplicationContextAware}
	 *
	 * @return {@link ListableBeanFactory}
	 * @since 5.7.0
	 */
	public static ListableBeanFactory getBeanFactory() {
		final ListableBeanFactory factory = null == beanFactory ? applicationContext : beanFactory;
		if (null == factory) {
			throw new UtilException("No ConfigurableListableBeanFactory or ApplicationContext injected, maybe not in the Spring environment?");
		}
		return factory;
	}

	/**
	 * 获取{@link ConfigurableListableBeanFactory}
	 *
	 * @return {@link ConfigurableListableBeanFactory}
	 * @throws UtilException 当上下文非ConfigurableListableBeanFactory抛出异常
	 * @since 5.7.7
	 */
	public static ConfigurableListableBeanFactory getConfigurableBeanFactory() throws UtilException {
		final ConfigurableListableBeanFactory factory;
		if (null != beanFactory) {
			factory = beanFactory;
		} else if (applicationContext instanceof ConfigurableApplicationContext) {
			factory = ((ConfigurableApplicationContext) applicationContext).getBeanFactory();
		} else {
			throw new UtilException("No ConfigurableListableBeanFactory from context!");
		}
		return factory;
	}

在Bean注册时,已经完成了BeanFactory的实例化,可以直接调用getBean等方法了。

  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值