Contents

Spring 配置注入非托管类

1. 概述

根据设计,使用*@Repository*、@Service@Controller等注解的类由 Spring 管理,并且注入配置很容易和自然。不那么简单的是将配置传递给不由 Spring 直接管理的类。

在这种情况下,我们可以使用基于ClassLoader的配置加载或简单地在另一个 bean 中实例化我们的类并手动设置所需的参数——这是建议的选项,因为配置条目不需要专门存储在 *.properties 文件中。

在这篇快速文章中,我们将介绍使用 Java ClassLoader加载 *.properties 文件以及将Spring 已加载的配置 注入非托管类的主题。

2. 使用类加载器加载配置

简单地说, *.properties 文件是包含一些配置信息的资源文件。代替使用支持自动应用程序配置加载的第三方实现,例如在 Spring 中实现的,我们可以使用 Java ClassLoader来做同样的事情。

我们将创建一个容器对象,该对象将保存在resourceFileName中定义的Properties。为了用配置填充容器,我们将使用ClassLoader

让我们定义实现loadProperties(String resourceFileName)方法的PropertiesLoader类:

public class PropertiesLoader {
    public static Properties loadProperties(String resourceFileName) throws IOException {
        Properties configuration = new Properties();
        InputStream inputStream = PropertiesLoader.class
          .getClassLoader()
          .getResourceAsStream(resourceFileName);
        configuration.load(inputStream);
        inputStream.close();
        return configuration;
    }
}

每个Class对象都包含对实例化它的ClassLoader的引用;这是一个主要负责加载类的对象,但在本教程中,我们将使用它来加载资源文件而不是普通的 Java 类。ClassLoader正在类路径中查找resourceFileName

之后,我们通过getResourceAsStream API将资源文件加载为InputStream

在上面的示例中,我们定义了一个可以使用load(InputStream) API解析resourceFileName的配置容器。

load 方法实现对 *.properties 文件的解析,支持*“:”“=”字符作为分隔符。此外,“#”“!”* 新行开头使用的字符是注解标记,会导致该行被忽略。

最后,让我们从配置文件中读取已定义配置条目的确切值:

String property = configuration.getProperty(key);

3. 使用 Spring 加载配置

第二种解决方案是利用 Spring Spring 特性来处理文件的一些低级加载和处理。

让我们定义一个Initializer来保存初始化我们的自定义类所需的配置。在Bean初始化期间,框架将从 *.properties 配置文件中加载所有带有*@Value*注解的字段:

@Component
public class Initializer {
    private String someInitialValue;
    private String anotherManagedValue;
    public Initializer(
      @Value("someInitialValue") String someInitialValue,
      @Value("anotherValue") String anotherManagedValue) {
 
        this.someInitialValue = someInitialValue;
        this.anotherManagedValue = anotherManagedValue;
    }
    public ClassNotManagedBySpring initClass() {
        return new ClassNotManagedBySpring(
          this.someInitialValue, this.anotherManagedValue);
    }
}

Initializer现在可以负责实例化ClassNotManagedBySpring

现在我们将简单地访问我们的Initializer实例并在其上运行initClass()方法来处理我们自定义ClassNotManagedBySpring的实例化:

ClassNotManagedBySpring classNotManagedBySpring = initializer.initClass();

一旦我们有了对Initializer的引用,我们就可以实例化我们的自定义ClassNotManagedBySpring