jjzjj

java - 我可以在没有 Spring AppContext 的情况下手动加载 @ConfigurationProperties 吗?

coder 2024-03-15 原文

有什么方法可以在不直接使用 Spring Context 的情况下加载标有 @ConfigurationProperties 的类?基本上我想重用 Spring 所做的所有智能逻辑,但对于我在 Spring 生命周期之外手动实例化的 bean。

我有一个在 Spring (Boot) 中愉快加载的 bean,我可以将它注入(inject)到我的其他服务 bean 中:

@ConfigurationProperties(prefix="my")
public class MySettings {
    String property1;
    File property2;
} 

有关更多信息,请参阅 spring docco http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-external-config-command-line-args

但现在我需要从在 Spring 之外(由 Hibernate)创建的类访问这个 bean。该类在应用程序启动过程中创建得如此之早,以至于 Spring Boot 尚未通过经典的查找帮助器方法或 roll-my-own 静态引用使应用程序上下文可用。

所以我反而想做这样的事情:

MySettings mySettings = new MySettings(); 
SpringPropertyLoadingMagicClass loader = new SpringPropertyLoadingMagicClass();
loader.populatePropertyValues(mySettings);

并且让 MySettings 最终从命令行、系统属性、app.properties 等加载所有值。Spring 中是否有某个类执行类似的操作,或者它是否与应用程序上下文交织在一起?

显然我可以自己加载 Properties 文件,但我真的想保留 Spring Boot 围绕使用命令行变量(例如 --my.property1=xxx)、系统变量、application.properties 甚至 yaml 的逻辑文件,以及它围绕宽松绑定(bind)和类型转换的逻辑(例如 property2 是一个文件),因此它的工作方式与在 Spring 上下文中使用时完全相同。

可能还是白日梦?

感谢您的帮助!

最佳答案

我有同样的“问题”。 这是我在 SpringBoot 版本 1.3.xxx 和 1.4.1 中解决它的方法。

假设我们有以下 yaml 配置文件:

foo:
  apis:
      -
       name: Happy Api
       path: /happyApi.json?v=bar
      -
       name: Grumpy Api
       path: /grumpyApi.json?v=grrr

我们有以下ConfigurationProperties:

@ConfigurationProperties(prefix = "foo")
public class ApisProperties {
    private List<ApiPath> apis = Lists.newArrayList();

    public ApisProperties() {
    }

    public List<ApiPath> getApis() {
        return apis;
    }

    public static class ApiPath {
        private String name;
        private String path;

        public String getName() {
            return name;
        }

        public void setName(final String aName) {
            name = aName;
        }

        public String getPath() {
            return path;
        }

        public void setPath(final String aPath) {
            path = aPath;
        }
    }
} 

然后,要以编程方式 执行 Spring Boot 的“神奇”操作(例如,在静态方法中加载一些属性),您可以执行以下操作:

private static ApisProperties apiProperties() {
    try {
        ClassPathResource resource;
        resource = new ClassPathResource("/config/application.yml");

        YamlPropertiesFactoryBean factoryBean;
        factoryBean = new YamlPropertiesFactoryBean();
        factoryBean.setSingleton(true); // optional depends on your use-case
        factoryBean.setResources(resource);

        Properties properties;
        properties = factoryBean.getObject();

        MutablePropertySources propertySources;
        propertySources = new MutablePropertySources();
        propertySources.addLast(new PropertiesPropertySource("apis", properties));

        ApisProperties apisProperties;
        apisProperties = new ApisProperties();

        PropertiesConfigurationFactory<ApisProperties> configurationFactory;
        configurationFactory = new PropertiesConfigurationFactory<>(apisProperties);
        configurationFactory.setPropertySources(propertySources);
        configurationFactory.setTargetName("foo"); // it's the same prefix as the one defined in the @ConfigurationProperties

        configurationFactory.bindPropertiesToTarget();
        return apisProperties; // apiProperties are fed with the values defined in the application.yaml

    } catch (BindException e) {
        throw new IllegalArgumentException(e);

    }
}

关于java - 我可以在没有 Spring AppContext 的情况下手动加载 @ConfigurationProperties 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26940583/

有关java - 我可以在没有 Spring AppContext 的情况下手动加载 @ConfigurationProperties 吗?的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  3. ruby - 我可以使用 Ruby 从 CSV 中删除列吗? - 2

    查看Ruby的CSV库的文档,我非常确定这是可能且简单的。我只需要使用Ruby删除CSV文件的前三列,但我没有成功运行它。 最佳答案 csv_table=CSV.read(file_path_in,:headers=>true)csv_table.delete("header_name")csv_table.to_csv#=>ThenewCSVinstringformat检查CSV::Table文档:http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV/Table.html

  4. ruby - 默认情况下使选项为 false - 2

    这是在Ruby中设置默认值的常用方法:classQuietByDefaultdefinitialize(opts={})@verbose=opts[:verbose]endend这是一个容易落入的陷阱:classVerboseNoMatterWhatdefinitialize(opts={})@verbose=opts[:verbose]||trueendend正确的做法是:classVerboseByDefaultdefinitialize(opts={})@verbose=opts.include?(:verbose)?opts[:verbose]:trueendend编写Verb

  5. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  6. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  7. ruby - 我可以使用 aws-sdk-ruby 在 AWS S3 上使用事务性文件删除/上传吗? - 2

    我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的

  8. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  9. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  10. ruby - 有人可以帮助解释类创建的 post_initialize 回调吗 (Sandi Metz) - 2

    我正在阅读SandiMetz的POODR,并且遇到了一个我不太了解的编码原则。这是代码:classBicycleattr_reader:size,:chain,:tire_sizedefinitialize(args={})@size=args[:size]||1@chain=args[:chain]||2@tire_size=args[:tire_size]||3post_initialize(args)endendclassMountainBike此代码将为其各自的属性输出1,2,3,4,5。我不明白的是查找方法。当一辆山地自行车被实例化时,因为它没有自己的initialize方法

随机推荐