Java 如何避免多次读取属性文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18517291/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 08:43:06  来源:igfitidea点击:

How to avoid reading property file multiple times

java

提问by Austin

We have some data in properties file. This data is used across many classes. So, we create a Properties class object in each and every class and then read data using getProperty() method. This is leading to duplication of code.

我们在属性文件中有一些数据。该数据用于许多类。因此,我们在每个类中创建一个 Properties 类对象,然后使用 getProperty() 方法读取数据。这导致代码重复。

Can someone please suggest some best practices to avoid this?

有人可以建议一些最佳做法来避免这种情况吗?

One thing that came to my mind is:
Create a class
Have a public variable for each property in property file in this class
Have a method that assigns values to each and every property
In the class where property values are required, create an object for this class and access the public variables

我想到的一件事是:
创建一个类
为此类中的属性文件中的每个属性创建一个公共变量 有一个为每个属性赋值
的方法
在需要属性值的类中,为此创建一个对象类并访问公共变量

But, things i don't like with this approach are public variables and if at all a new property is added to the property file, i need to add code to read that property in the class.

但是,我不喜欢这种方法的事情是公共变量,如果在属性文件中添加了一个新属性,我需要添加代码来读取类中的该属性。

Any help is appreciated.

任何帮助表示赞赏。

Thank you!

谢谢!

回答by codethulhu

One out of the box option is to use system properties. You can add your own system properties to your execution environment.

一种开箱即用的选项是使用系统属性。您可以将自己的系统属性添加到您的执行环境中。

回答by Joe

You can do this with a dedicated class having a static Properties object. See herefor an example.

您可以使用具有静态 Properties 对象的专用类来执行此操作。有关示例,请参见此处

回答by Henry Keiter

I could be misunderstanding your data flow here, but this is what seems "normal" to me:

我可能会误解您的数据流,但这对我来说似乎是“正常的”:

  • Create a readPropFilemethod.
    • This should read a file and appropriately parse the properties it finds.
    • These properties can be stored in a Map<String, Object>, hashed by property name.
  • Read property file once (presumably when the application starts, or whenever it's appropriate to load properties) --> Propertiesobject (say, props).
  • Pass propsaround to anything that needs access to those properties.
    • Or if you don't want to pass it around explicitly, use a static accessor as illustrated here.
  • Access properties using props.get("PROPERTY_NAME")(which just looks up that property in the internal Map).
    • If you don't want to use String lookups, you can keep an enum of valid property names somewhere, and do storage/lookups using that, but then you have to update that enum every time you add a new property to the file.
  • 创建readPropFile方法。
    • 这应该读取一个文件并适当地解析它找到的属性。
    • 这些属性可以存储在Map<String, Object>按属性名称散列的 中。
  • 读取一次属性文件(大概是在应用程序启动时,或者在适合加载属性时)-->Properties对象(例如,props)。
  • 传递props给需要访问这些属性的任何内容。
    • 或者,如果你不想通过它围绕明确,使用静态访问如图所示这里
  • 访问属性使用props.get("PROPERTY_NAME")(它只是在内部查找该属性Map)。
    • 如果您不想使用字符串查找,您可以在某处保留有效属性名称的枚举,并使用它进行存储/查找,但是每次向文件添加新属性时都必须更新该枚举。

回答by Cristian Meneses

You can create a Singleton class, that loads the properties the first time it gets invoked.. and a public method that retrieves the property value, for a given property key..

您可以创建一个 Singleton 类,该类在第一次调用时加载属性......以及一个检索属性值的公共方法,对于给定的属性键......

This is assuming you're using a standart Properties file... But you can extrapolate this to any key-value pair, changing Properties type to a Map or something else.

这是假设您使用的是标准属性文件...但是您可以将其推断为任何键值对,将属性类型更改为 Map 或其他内容。

Something like

就像是

public class PropertyHandler{

   private static PropertyHandler instance = null;

   private Properties props = null;

   private PropertyHandler(){
         // Here you could read the file into props object
         this.props = ..... 
   }

   public static synchronized PropertyHandler getInstance(){
       if (instance == null)
           instance = new PropertyHandler();
       return instance;
   }

   public String getValue(String propKey){
       return this.props.getProperty(propKey);
   }
}

Then you can invoke this as needed.. from any code.. like this.

然后你可以根据需要调用它......从任何代码......像这样。

String myValue = PropertyHandler.getInstance().getValue(propKey);

Hope this helps

希望这可以帮助

回答by Magnus

I've had success using an Enum, and in the constructor using the name() method to read a property of the same name. Be sure to handle exceptions in a reasonable way or else the whole class will fail to load and you won't get a helpful error message.

我已经成功使用枚举,并在构造函数中使用 name() 方法读取同名属性。确保以合理的方式处理异常,否则整个类将无法加载,并且您不会收到有用的错误消息。

Benefits of this approach are that each enum value automatically corresponds to a property without having to write individual mapping code for each property. You do of course need an enum value for each property (that's unavoidable if you want DRY prop references), but you avoid repetitive per-property initialization code using unchecked Strings.

这种方法的好处是每个枚举值自动对应一个属性,而不必为每个属性编写单独的映射代码。您当然需要每个属性的枚举值(如果您想要 DRY 属性引用,这是不可避免的),但是您可以避免使用未经检查的字符串重复每个属性的初始化代码。

Drawbacks are that enums don't allow generic types, so if you wanted certain properties to return Integer and others to return String, then you might be better served with a classic singleton class design.

缺点是枚举不允许泛型类型,因此如果您希望某些属性返回 Integer 而其他属性返回 String,那么使用经典的单例类设计可能会更好。

If you want to go crazy with this you could also write a script to generate your Enum or singleton java source code from the properties file, to keep your code extra DRY.

如果您想为此疯狂,您还可以编写一个脚本来从属性文件生成您的 Enum 或单例 Java 源代码,以使您的代码保持额外干燥。

回答by Trying

for me static inner class is the best possible way to do it. It will do it with lazily, as class loading is synchronized so thread safe, plus performant also. So with this we are achieving three things:

对我来说,静态内部类是最好的方法。它会懒惰地做到这一点,因为类加载是同步的,因此线程安全,而且性能也很好。因此,我们正在实现三件事:

  1. good performance because with synchronizing the liveliness will suffer, but here we are using static inner class.
  2. thread safety because when inner class will be loaded than only map will be initialized as the class loading is thread safe hence all total thread safe.
  3. Inner class will be loaded when we will call Singleton.initialize().get(key)so the map gets initialized lazily.
  1. 良好的性能,因为同步时活跃度会受到影响,但这里我们使用的是静态内部类。
  2. 线程安全,因为当加载内部类时,只会初始化映射,因为类加载是线程安全的,因此所有线程都是安全的。
  3. 当我们调用时将加载内部类,Singleton.initialize().get(key)以便延迟初始化地图。

Below is the code...

下面是代码...

public class SingletonFactory 
{   
    private static class Singleton
    {
        private static final Map<String, String> map = new HashMap<String, String>();
        static
        {
            try
            {
                //here we can read properties files
                map.put("KEY", "VALUE");
            }
            catch(Exception e)
            {
                //we can do the exception handling
                System.out.println(e);
            }
        }
        private static Map<String, String> initialize()
        {   
            return map;
        }
    }

    public static String getValue(String key)
    {
        return Singleton.initialize().get(key);
    }
}