【问题标题】:Autowired not working in Bean class SpringAutowired 在 Bean 类 Spring 中不起作用
【发布时间】:2018-10-04 18:53:33
【问题描述】:

我正在尝试创建一个 bean 并实例化覆盖默认构造函数的 bean 属性,并使用 Environment [org.springframework.core.env.Environment] 的对象从属性文件中获取和分配属性。

下面是我的属性文件 [mi.properties]

mi.name=GB
mi.grade=13

下面是我的简单 bean 类

public class School implements EnvironmentAware {

private String schoolName;
private int schoolGrade;
private int totalStudents;

public School(Environment env) {
    this.schoolName = env.getProperty("mi.name", "MT");
    this.schoolGrade = env.getProperty("mi.grade", Integer.class, 10);
    this.totalStudents = env.getProperty("mi.total", Integer.class, 1000);
}

public School() {
    this.schoolName = this.env.getProperty("mi.name", "MT");
    this.schoolGrade = this.env.getProperty("mi.grade", Integer.class, 10);
    this.totalStudents = this.env.getProperty("mi.total", Integer.class, 1000);
}
//Getter Setters
}

下面是我的 Java 配置类

@Configuration
@PropertySource("classpath:/cross/mi.properties")
public class JavaConfig {
@Autowired
private Environment env;

@Bean
public School getSchool()
{
    School obj = new School(env);
    return obj;
}
}

这将正确地创建 School bean。但是,当我尝试在 School bean 中自动装配 Environment 时,它并没有创建 bean。

以下是我尝试过的

public class School implements EnvironmentAware {

private String schoolName;
private int schoolGrade;
private int totalStudents;

@Autowired
private Environment env;

public School(Environment env) {
    this.schoolName = env.getProperty("mi.name", "MT");
    this.schoolGrade = env.getProperty("mi.grade", Integer.class, 10);
    this.totalStudents = env.getProperty("mi.total", Integer.class, 1000);
}

public School() {
    this.schoolName = this.env.getProperty("mi.name", "MT");
    this.schoolGrade = this.env.getProperty("mi.grade", Integer.class, 10);
    this.totalStudents = this.env.getProperty("mi.total", Integer.class, 1000);
}
//Getter Setters
}

Java 配置更改如下

@Configuration
@PropertySource("classpath:/cross/mi.properties")
@ComponentScan
public class JavaConfig {
@Bean
public School getSchool()
{
    School obj = new School();
    return obj;
}
}

这不是在 Spring 上下文中创建 School bean,当我调试时,覆盖的默认构造函数中的 Environment 实例是 null 因此 getProperty() 方法失败。

我对此有点困惑。

  1. 据我了解,Spring 生命周期上下文将在构造函数调用之前自动装配所有 @autowired 属性。对吗?

  2. 如果在 Spring 生命周期中解决所有自动装配的属性时上述语句错误?

  3. 根据 JVM 架构,它会在第一次加载类时分配内存并为类的属性分配默认值。这是否意味着默认加载 School 类时,其属性 env 默认为 null ?

  4. JavaConfig 类中的自动装配环境如何工作? Spring 如何自动装配此值以及在其生命周期的哪个阶段?

正如一些论坛所建议的,我已经尝试在 School 类中实现 EnvironmentAware 接口,并将@Component 注释添加到 School 类。仍然没有结果。

【问题讨论】:

    标签: java spring inversion-of-control autowired


    【解决方案1】:

    Spring 在构造函数执行并创建实例后使用反射注入@Autowired 属性。这就是为什么你总是在构造函数中得到 null —— Spring 还没有设置类的属性。

    您可以通过多种方式实现您想要的。一种是使用

    afterPropertiesSet() 方法在属性设置后按照名称执行 :) 你将拥有 env

    我更喜欢的另一种解决方案是在构造函数中添加自动装配的 bean。有人称之为构造函数注入。

    它会将使用 Environment 的构造函数标记为自动装配(或只有一个构造函数):

    @Autowired
    public School(Environment env) {
        this.schoolName = env.getProperty("mi.name", "MT");
        this.schoolGrade = env.getProperty("mi.grade", Integer.class, 10);
        this.totalStudents = env.getProperty("mi.total", Integer.class, 1000);
    }
    

    通过这种方式,您还可以将环境变量设置为 final(这将是一个好主意)。这将与其他人建议的 @component 注释一起使用,以便删除使用 new School() 手动创建 bean

    查看link了解更多信息

    【讨论】:

    • 谢谢你的解释。
    • 没问题。我希望我有所帮助。您总是可以通过投票或接受答案来感谢我☺️
    【解决方案2】:

    注入发生在构造之后,除非你明确地使用构造函数注入:

    @Autowired
    public School(Environment env) {
        this.schoolName = env.getProperty("mi.name", "MT");
        this.schoolGrade = env.getProperty("mi.grade", Integer.class, 10);
        this.totalStudents = env.getProperty("mi.total", Integer.class, 1000);
    }
    

    另一种选择是使用@PostConstruct 方法进行初始化:

    @Autowired
    private Environment env;
    
    public School() {
    }
    
    @PostConstruct
    public void initialise() {
        this.schoolName = this.env.getProperty("mi.name", "MT");
        this.schoolGrade = this.env.getProperty("mi.grade", Integer.class, 10);
        this.totalStudents = this.env.getProperty("mi.total", Integer.class, 1000);
    }
    

    【讨论】:

    • 感谢您的洞察力。但是我对 Spring 生命周期中的 Bean 创建过程仍然感到有些困惑。它与JVM类加载和链接过程相同吗?还是有一点不同?构造后,所有属性将首先设置或使用@PostConstruct 注释的方法被调用?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-25
    相关资源
    最近更新 更多