关于spring中environment注入为null的一点理解

本文深入探讨Spring框架中Bean的三种注入方式:普通JavaBean、系统环境Bean及实现Aware接口的Bean。解析了每种方式的工作原理,包括自动注入的配置与常见问题解决策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在学习spring的源码 ,在学习中经常出现一件事,就是自动注入的某些属性不知道忘了那些配置经常会出现null的现象,现在做一些统一整理:

首先:spring中的bean从注入方式上会分成三种,一种是普通的javaBean,就是自己在配置文件中写好的放在容器中的,在一种就是系统环境bean,包括三个,Environment,SystemPropertits,SystemEnvironment,还有一种是实现了XXXAware接口的bean,

第一种不解释

第二种,这种bean不是我们自己创建的,而是spring帮我们自动创建的,spring代码如下:

        // Register default environment beans.
        if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
            beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
        }
        if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
            beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
        }
        if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
            beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
        }

儿上面的getEnvironment()方法的代码如下:

public ConfigurableEnvironment getEnvironment() {
   if (this.environment == null) {
      this.environment = createEnvironment();
   }
   return this.environment;
}
protected ConfigurableEnvironment createEnvironment() {
   return new StandardEnvironment();
}

默认会返回一个Environment接口的实现StandardEnvironment;用来存贮我们所需要的属性;

第三种,实现XXXAware接口的类

代码如下:

private void invokeAwareMethods(String beanName, Object bean) {
    if (bean instanceof Aware) {
        if (bean instanceof BeanNameAware) {
            ((BeanNameAware)bean).setBeanName(beanName);
        }

        if (bean instanceof BeanClassLoaderAware) {
            ((BeanClassLoaderAware)bean).setBeanClassLoader(this.getBeanClassLoader());
        }

        if (bean instanceof BeanFactoryAware) {
            ((BeanFactoryAware)bean).setBeanFactory(this);
        }
    }

}

這是系統默认的几个Aware,其他的Aware实现与之类似,具体使用方法如下:

public class Student  implements EnvironmentAware {
    Environment environment;

    private int id;
    public Student(int id) {
        this.id=id;
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.environment=environment;
    }
}

测试代码

public class Main {

    public static void main (String[] args){
        ApplicationContext context=new ClassPathXmlApplicationContext("classpath:resources\\META-INF\\spring\\camel-context.xml");
        System.out.println(((Student)context.getBean("xiaoming")).environment==null);
        
    }
}

结果:

原理就是使用了个回调方法,也没啥说的

这三种方式,在不显式声明使用自动注入的情况下,第一种与第二种将不会注入到自己创建的javaBean之中,在开启自动注入的情况下,也就是说在配置文件中添加

component-scan

子元素,前两种的属性将会注入到所创建的javaBean之中;

总结,当所创建的javaBean之中属性出现null时,考虑如下解决方式:

1.仔细查看配置文件与配置类,是否声明了相关的类型,且

constructor-arg 
property 等配置文件的相关子元素是否配置得当

IDEA编译器为spring提供了相当强的插件支持,建议换个编译器~~~~

2.若是属性在配置文件或者配置类里面已经声明且符合唯一约束;

3.若是使用了@Autowire等相关注解,查看是否开启了自动注解,开启自动注解方法是;在相关的配置文件或者配置类里面声明

<context:component-scan/>

或者是

@ComponentScan 注解

4。此时会解决绝大部分null问题,当仍为null,考虑实现相关的Aware接口,比如ApplicationContextAware,此时他会将ApplicationContext注入到你的javaBean中,而一般情况下他不会给你自动注入的;

<think>好的,我现在需要解决用户提到的Knife4jAutoConfiguration中Environmentnull的问题。用户提到了他们正在使用Spring Cloud Gateway整合Knife4j 4.4.0实现微服务聚合文档,并且在子模块中引入了相应的依赖。根据他们提供的引用内容,他们可能是在配置网关聚合时遇到了问题。 首先,我需要回忆一下Spring Boot的自动配置机制。通常,自动配置类如Knife4jAutoConfiguration会依赖Environment来读取配置属性。如果Environmentnull,可能是由于配置类在初始化时未能正确获取到环境变量。这种情况通常发生在Bean的加载顺序有问题,或者某些必要的配置未正确加载的情况下。 接下来,我需要考虑可能的原因。根据用户的情况,他们可能在网关模块中手动配置了Knife4j的Bean,而没有正确传递Environment。例如,如果在@Configuration类中直接new了一个Knife4j的配置实例,而没有通过Spring的依赖注入,那么Environment可能不会被自动注入,导致null的情况。 另一个可能的原因是依赖冲突或版本不兼容。用户使用的是Knife4j 4.4.0,需要确认该版本是否与Spring Boot或Spring Cloud Gateway的版本兼容。如果存在版本不匹配,可能会导致某些自动配置类无法正常初始化,进而导致Environment未被注入。 此外,用户提到在网关聚合Knife4j时没有开启服务发现,而是手动配置路由。这可能意味着某些自动配置的条件未被满足,例如缺少服务发现相关的依赖或配置,导致Knife4jAutoConfiguration未能正确初始化。不过,手动配置路由通常不会直接影响Environment注入,除非在配置过程中有误。 针对这些问题,我需要给出具体的解决步骤。首先,检查依赖是否正确引入,确保没有版本冲突。然后,确认是否在配置类中正确使用了@Autowired来注入Environment,或者是否手动实例化了配置类而没有依赖注入。此外,可能需要检查Spring Boot的启动类是否缺少必要的注解,导致自动配置未生效。 最后,建议用户查看Knife4j的官方文档或社区讨论,看看是否有类似的问题和解决方案。可能还需要检查日志输出,查看是否有相关的错误信息,帮助进一步定位问题。</think>### Knife4jAutoConfiguration中Environmentnull的解决方案 #### 1. 检查依赖引入方式 确保子模块中引入的`knife4j-openapi2-spring-boot-starter`依赖**未声明版本号**,避免版本冲突。正确配置如下: ```xml <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-openapi2-spring-boot-starter</artifactId> </dependency> ``` 若父工程未统一管理版本号,需在`<dependencyManagement>`中指定Knife4j版本[^1]。 #### 2. 验证自动配置触发条件 在`application.yml`中**显式启用Knife4j**: ```yaml knife4j: enable: true # 其他配置项... ``` 检查是否有`@EnableKnife4j`或`@EnableSwagger2WebFlux`注解遗漏(根据网关类型选择)[^2]。 #### 3. 处理自定义配置类 若存在手动创建的配置类,需**通过Spring注入Environment**: ```java @Configuration public class GatewayKnife4jConfig { @Autowired // 关键点 private Environment environment; @Bean public OpenAPI customOpenAPI() { return new OpenAPI() .info(new Info().title(environment.getProperty("spring.application.name"))); } } ``` #### 4. 检查Bean加载顺序 在启动类添加**依赖自动配置类的显式引入**: ```java @SpringBootApplication( exclude = { // 若有其他冲突配置可在此排除 }, scanBasePackages = { "com.github.xiaoymin.knife4j.spring.configuration" } ) public class GatewayApplication { public static void main(String[] args) { SpringApplication.run(GatewayApplication.class, args); } } ``` #### 5. 调试日志分析 在`application.yml`中开启调试日志: ```yaml logging: level: com.github.xiaoymin: DEBUG org.springframework.context: DEBUG ``` 观察控制台输出是否包含: ``` Knife4jAutoConfiguration#initializing... Environment injected: org.springframework.core.env.StandardEnvironment ``` #### 6. 版本兼容性验证 推荐版本组合: ```xml <properties> <spring-boot.version>2.7.18</spring-boot.version> <spring-cloud.version>2021.0.8</spring-cloud.version> <knife4j.version>4.4.0</knife4j.version> </properties> ``` 避免使用Spring Boot 3.x与Knife4j 4.x的直接组合,需验证官方兼容性说明。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值