opengoofy/crane4j

Springboot3.0启动警告

Closed this issue · 4 comments

你的依赖版本与运行环境

  • JDK 版本:17
  • Crane4j 版本:2.9.0
  • 相关依赖版本:Springboot 3.2.1

描述你的问题或需求

在springboot3.0环境下,项目在启动时会出现如下警告,不过不影响使用,大佬有空处理下吗?
Bean 'cn.crane4j.spring.boot.config.Crane4jAutoConfiguration' of type [cn.crane4j.spring.boot.config.Crane4jAutoConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [whiteApiProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies.
image

Crane4j 有些自定义的 BeanPostProcessor 会依赖 Crane4jAutoConfiguration ,所以这个 Bean 的加载时机特别的早,不过一般来说不会有什么问题。

下个版本会调整一下它的权限为 BeanDefinition.ROLE_INFRASTRUCTURE,这样应该就能避免这个问题了。不过你也可以在你的配置类里面按这样重新声明一个 Crane4jApplicationContext,理论上这样也可以生效:

@Role(BeanDefinition.ROLE_INFRASTRUCTURE) // 调整权限
@Primary
@ConditionalOnMissingBean
@Bean
public Crane4jApplicationContext crane4jApplicationContext(
    ApplicationContext applicationContext, Properties properties) {
  Crane4jApplicationContext context = new Crane4jApplicationContext(applicationContext);
  context.setAllowContainerOverriding(properties.isAllowContainerOverriding());
  return context;
}

这个警告在下个版本应该就不会出现了,具体参见:1b17383443844f304e25769055ac5939dc280de6。

不过我又回头过来看了一下,警告里面似乎提到了一个你自定义的 BeanPostProcessor 组件 whiteApiProcessor,这个组件里面是不是直接依赖了 Crane4jAutoConfiguration?如果方便的话,能看看你在这个组件里面是如何依赖 Crane4jAutoConfiguration 的吗?

大概的逻辑是这样的:这边定义了一个注解: WhiteApi,这个注解主要用于Controller层,然后通过WhiteApiProcessor来记录所有有该注解的url,将这些url设为访问的白名单
`

package com.ln.common.web.config;
import java.lang.annotation.*;

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WhiteApi {

    boolean sign() default false;

}

package com.ln.common.web.config;

import com.ln.common.web.annotation.WhiteApi;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hutool.core.annotation.AnnotatedElementUtil;
import org.dromara.hutool.core.reflect.method.MethodUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;

import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;

@Component
@Slf4j
public class WhiteApiProcessor implements BeanPostProcessor {

    public static Set<String> WHILE_URL = new HashSet<>();

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        RequestMapping controllerMapping = AnnotatedElementUtil.getResolvedAnnotation(bean.getClass(), RequestMapping.class);
        if (controllerMapping == null) {
            return bean;
        }
        WhiteApi whiteApiController = bean.getClass().getAnnotation(WhiteApi.class);
        Method[] methods = MethodUtil.getMethods(bean.getClass());
        for (Method method : methods) {
            RequestMapping mapping = AnnotatedElementUtil.getResolvedAnnotation(method, RequestMapping.class);
            if (mapping == null) {
                continue;
            }
            if (whiteApiController == null) {
                WhiteApi whiteApi = method.getAnnotation(WhiteApi.class);
                if (whiteApi == null) {
                    continue;
                }
            }
            String[] controllerMappingValues = controllerMapping.value();
            if (controllerMapping.value().length == 0) {
                controllerMappingValues = new String[]{""};
            }
            for (String controllerMappingValue : controllerMappingValues) {
                for (String methodMappingValue : mapping.value()) {
                    if (methodMappingValue.contains("{")) {
                        methodMappingValue = StrUtil.subBefore(methodMappingValue, "{", true) + "*";
                    }
                    String url = controllerMappingValue + methodMappingValue;
                    if (!controllerMappingValue.endsWith("/") && !methodMappingValue.startsWith("/")) {
                        url = controllerMappingValue + "/" + methodMappingValue;
                    }
                    log.info("添加url白名单:" + url);
                    WHILE_URL.add(url);
                }
            }
        }
        return bean;
    }

}

`

大概的逻辑是这样的:这边定义了一个注解: WhiteApi,这个注解主要用于Controller层,然后通过WhiteApiProcessor来记录所有有该注解的url,将这些url设为访问的白名单 `

package com.ln.common.web.config;
import java.lang.annotation.*;

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WhiteApi {

    boolean sign() default false;

}

package com.ln.common.web.config;

import com.ln.common.web.annotation.WhiteApi;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hutool.core.annotation.AnnotatedElementUtil;
import org.dromara.hutool.core.reflect.method.MethodUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;

import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;

@Component
@Slf4j
public class WhiteApiProcessor implements BeanPostProcessor {

    public static Set<String> WHILE_URL = new HashSet<>();

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        RequestMapping controllerMapping = AnnotatedElementUtil.getResolvedAnnotation(bean.getClass(), RequestMapping.class);
        if (controllerMapping == null) {
            return bean;
        }
        WhiteApi whiteApiController = bean.getClass().getAnnotation(WhiteApi.class);
        Method[] methods = MethodUtil.getMethods(bean.getClass());
        for (Method method : methods) {
            RequestMapping mapping = AnnotatedElementUtil.getResolvedAnnotation(method, RequestMapping.class);
            if (mapping == null) {
                continue;
            }
            if (whiteApiController == null) {
                WhiteApi whiteApi = method.getAnnotation(WhiteApi.class);
                if (whiteApi == null) {
                    continue;
                }
            }
            String[] controllerMappingValues = controllerMapping.value();
            if (controllerMapping.value().length == 0) {
                controllerMappingValues = new String[]{""};
            }
            for (String controllerMappingValue : controllerMappingValues) {
                for (String methodMappingValue : mapping.value()) {
                    if (methodMappingValue.contains("{")) {
                        methodMappingValue = StrUtil.subBefore(methodMappingValue, "{", true) + "*";
                    }
                    String url = controllerMappingValue + methodMappingValue;
                    if (!controllerMappingValue.endsWith("/") && !methodMappingValue.startsWith("/")) {
                        url = controllerMappingValue + "/" + methodMappingValue;
                    }
                    log.info("添加url白名单:" + url);
                    WHILE_URL.add(url);
                }
            }
        }
        return bean;
    }

}

`

看起来似乎没什么问题,这个警告先忽略吧,下个版本应该就不会继续出现了 :)

另外,看代码你似乎引了 6.x 版本的 Hutool?Hutool 的 AnnotatedElementUtil 设计还有待完善,后面不出意外的话应该还会有一点调整,在 Spring 环境的话,这里还是比较推荐优先使用 Spring 的 AnnotatedElementUtil.getMergedAnnotation