在 Spring Boot 2.3/Spring 5 中创建自定义工厂 Bean

Creating a custom FactoryBean in Sprint Boot 2.3/Spring 5

我有一个 spring-boot web 应用程序,它大部分都在工作;我的数据源由外部 application.properties 文件正确配置。

现在我想向该文件添加属性以帮助我在我的应用程序中实例化和配置 class 的两个实例。我有一个 APNsFactory,我目前手动实例化并使用 JNDI 配置,但我想摆脱 JNDI 调用:

    @Bean
    public
    APNsFactory
    apnsFactory()
        throws
            javax.naming.NamingException
    {
        sLogger.info("Configuring APNsFactory");

        InitialContext ctx = new InitialContext();

        APNsFactory f = new APNsFactory();
        f.setProductionKeystorePath((String) ctx.lookup("java:comp/env/apns/prod/keystorePath"));
        f.setProductionKeystorePassword((String) ctx.lookup("java:comp/env/apns/prod/keystorePassword"));
        f.setDevelopmentKeystorePath((String) ctx.lookup("java:comp/env/apns/dev/keystorePath"));
        f.setDevelopmentKeystorePassword((String) ctx.lookup("java:comp/env/apns/dev/keystorePassword"));
        return f;
    }

当 运行 之前在独立的 webapp 容器中时,Spring 正确调用了该方法并且来自容器的 <env-entry> 标记的 JNDI 上下文可用。

我正在尝试将我的 APNsFactory 更新为一个合适的 Spring FactoryBean<>,并且我已经给了它几个我想要的 @Autowire String 变量由 Spring 从 application.properties 文件启动。

为了加分,我希望它既可以在 Spring Boot 中使用,也可以在 Tomcat 或 Resin 这样的独立容器中使用。

我这辈子都不知道如何让 Spring 做到这一点。 Spring 已经实现了 DataSources 和其他 Bean 的许多示例,但是 none 对于完全自定义的示例,使用 application.properties,在 Spring Boot web 环境中。

我看过一些使用 XML 配置文件的示例,但我不确定如何使用 Spring Boot.

我认为您在这里不需要工厂 bean。 您已经有 spring 可以读取 application.properties 开箱即用的引导:

所以请尝试以下操作:

  1. application.properties 文件中创建 key/values:
myapp.keystore.path=...
myapp.keystore.passwd=...
// the same for other properties
  1. 创建ConfigurationPropertiesclass

@ConfigurationProperties(prefix="myapp.keystore")
public class MyAppKeyStoreConfigProperties {

   private String path;  // the names must match to those defined in the properties file
   private String passwd;

   ... getters, setters
}

  1. 在标有 @Configuration 的 class 中(您创建 @Bean public APNsFactory apnsFactory() 的那个)执行以下操作:

@Configuration
// Note the following annotation:
@EnableConfigurationProperties(MyAppKeyStoreConfigProperties.class)
public class MyConfiguration {
   // Note the injected configuration parameter
   @Bean public APNsFactory apnsFactory(MyAppKeyStoreConfigProperties config) {
       APNsFactory f = new APNsFactory();
       f.setProductionKeystorePath(config.getKeyPath());
       and so on
   } 
}

我故意不显示 production/dev 之间的区别。 在 spring 引导中,您拥有配置文件,因此可以将相同的工件(WAR、JAR 等)配置为具有不同配置文件的 运行,并根据不同的配置文件读取相应的属性。

示例:

如果你是运行prod配置文件,那么除了无论如何都会加载的application.properties之外,你可以把这些keystore相关的定义放到application-prod.properties(后缀与配置文件名称匹配)- spring 引导将自动加载这些。当然,dev 个人资料也是如此。

现在我还没有完全理解 "bonus points" 任务 :) 这种机制是 spring 引导处理配置的专有方式。在 "standalone" 服务器中,它应该仍然有一个 WAR 和 spring 启动,所以它无论如何都会使用这个机制。或许你可以再说清楚,让我/我们的同事能提供更好的答案