在静态初始化块中加载 java 属性

Posted

技术标签:

【中文标题】在静态初始化块中加载 java 属性【英文标题】:Load java properties inside static initializer block 【发布时间】:2010-11-05 21:39:28 【问题描述】:

我有一个静态实用程序类,它对一些敏感数据进行一些字符串操作。 在使用这个类之前,我需要用值初始化某些静态变量,例如用户名/密码,我更喜欢将它们存储在 .properties 文件中。

我不太熟悉在 Java 中加载 .properties 文件的工作方式,尤其是在 *Spring DI *container 之外。 任何人都可以帮助我了解如何做到这一点?

谢谢!

补充: .properties 文件的精确位置未知,但它会在类路径上。有点像classpath:/my/folder/name/myproperties.propeties

【问题讨论】:

您提到了 Spring - 您是否在应用程序中使用包含此静态实用程序类的框架? 嗯,这有点奇怪。类将在使用 spring 容器的应用程序中使用。然而,类本身不会使用 spring 连接,它需要只是一个静态实用程序类,由 Spring 连接的工作线程调用。我可以修改工作线程,但我不能修改这些线程的接线(所以我不能使用 PropertyPlaceHolderConfigurer)......嗯,这有意义吗? :) 【参考方案1】:

首先,获取要从中加载属性的InputStream。这可能来自多个位置,包括一些最有可能的位置:

FileInputStream,使用硬编码或通过system property. 指定的文件名创建。名称可以是相对的(相对于 Java 进程的当前工作目录)或绝对的。 资源文件(类路径上的文件),通过在Class(相对于类文件)或ClassLoader(相对于类路径的根)上调用getResourceAsStream 获得。请注意,如果资源丢失,这些方法将返回 null,而不是引发异常。 URL,与文件名一样,可以硬编码或通过系统属性指定。

然后创建一个新的Properties 对象,并将InputStream 传递给它的load() 方法。一定要关闭流,不管有什么异常。

在类初始化器中,必须处理像IOException 这样的已检查异常。可以抛出未经检查的异常,这将阻止类被初始化。反过来,这通常会阻止您的应用程序运行。在许多应用程序中,可能需要改用默认属性,或者回退到其他配置源,例如在交互式上下文中提示使用。

总而言之,它可能看起来像这样:

private static final String NAME = "my.properties";

private static final Properties config;

static 
  Properties fallback = new Properties();
  fallback.put("key", "default");
  config = new Properties(fallback);

  URL res = MyClass.getResource(NAME);
  if (res == null) throw new UncheckedIOException(new FileNotFoundException(NAME));
  URI uri;
  try  uri = res.toURI(); 
  catch (URISyntaxException ex)  throw new IllegalArgumentException(ex); 

  try (InputStream is = Files.newInputStream(Paths.get(uri)))  config.load(is);  
  catch (IOException ex)  throw new UncheckedIOException("Failed to load resource", ex); 

【讨论】:

【参考方案2】:

    查看java.util.Properties。

    您可以使用静态初始化程序。所以在课堂上你可以做:


 static 
    Properties props = new Properties();
    InputStream steam = ...; // open the file
    props.load(stream);

    // process properties content
    String username = props.getProperty("username");
  

【讨论】:

对不起,我猜你在我做的时候已经在格式化代码了。 您可能需要一些异常处理,因为我不认为可以从静态块中抛出异常。 RuntimeExceptions 可以从静态块中抛出。您将需要处理文件操作的检查异常。 这里建议的实现主要是为了说明。要使其达到生产质量,您需要处理与文件相关的异常(例如安全性、存在性、IOException),在 finally 块中关闭连接,处理加密(我希望他不要以明文形式保存密码)等 【参考方案3】:

使用任一:

CurrentClassName.class.getResourceAsStream 
new FileInputStream(File)

根据类是否在类路径中来获取输入流。然后使用

Properties.load

加载属性。

【讨论】:

【参考方案4】:

已经有一段时间了,但如果我没记错的话,你只需这样做:

Properties prop = new Properties();
prop.load(new FileInputStream(filename));

//For each property you need.
blah = prop.getProperty(propertyname);

【讨论】:

【参考方案5】:

对于静态属性,将它们初始化为将在类中加载一次的单例是有意义的。这是一个例子:

class Example

    public final static String PROPSFILE = "test.properties";

    private static Properties props;

    protected static Properties getProperties()
    
        if(props == null)
        
            props = new Properties();
            props.load(new FileInputStream(new File(PROPSFILE));
        
        return props;
    

    public static User getUser()
    
        String username = getProperties().getProperty("username");
        return new User(username);
    

如果您使用相对路径名,您应该确保您的类路径设置正确。

【讨论】:

那不是单例。它只是一个静态变量和方法。该问题不需要公开访问属性,但需要从属性文件初始化静态成员。 好吧,我个人不喜欢静态初始化,因为它在我正在从事的项目中造成了一些麻烦。我建议尽可能使用至少静态工厂方法(我为此更新了示例)。但确实,这实际上不是问题。【参考方案6】:

对我来说 MyClass.class.getClassLoader().getResourceAsStream(..) 成功了:

private static final Properties properties;

static 
    Properties fallback = new Properties();
    fallback.put(PROP_KEY, FALLBACK_VALUE);

    properties = new Properties(fallback);

    try 
        try (InputStream stream = MyClass.class.getClassLoader().getResourceAsStream("myProperties.properties")) 
            properties.load(stream);
        
     catch (IOException ex) 
        // handle error
    

【讨论】:

【参考方案7】:

我同意@Daff,也许最好使用单例类...这是我在项目中对类似要求的要求,也许它可能会有所帮助:

类的客户可以这样使用它:

ConfigsLoader configsLoader = ConfigsLoader.getInstance("etc/configs.xml");

System.out.format("source dir %s %n", configsLoader.getSourceDir());

然后是班级:

公共类 ConfigsLoader

private String sourceDir;
private String destination;
private String activeMqUrl;

private static Logger log = Logger.getLogger(ConfigsLoader.class.getName());

private static ConfigsLoader instance = null;

private ConfigsLoader(String configFileName) 
    log.info("loading configs");
    Properties configs = new Properties();
    try 
        configs.loadFromXML(new FileInputStream(configFileName));

        sourceDir = configs.getProperty("source.dir");
        destination = configs.getProperty("destination");
        activeMqUrl = configs.getProperty("activemqconnectionurl");
        configs.setProperty("lastLoaded", new SimpleDateFormat("yyyy-M-d HH:mm").format(new Date()));
        configs.storeToXML(new FileOutputStream(configFileName), "saving last modified dates");

     catch (InvalidPropertiesFormatException e) 
        log.log(Level.SEVERE,"Error occured loading the properties file" ,e);
     catch (FileNotFoundException e) 
        log.log(Level.SEVERE,"Error occured loading the properties file" ,e);
     catch (IOException e) 
        log.log(Level.SEVERE,"Error occured loading the properties file" ,e);
    


public static ConfigsLoader getInstance(String configFileName) 
    if(instance ==null) 
        instance = new ConfigsLoader(configFileName);
    

    return instance;


public String getSourceDir() 
    return sourceDir;


public void setSourceDir(String sourceDir) 
    this.sourceDir = sourceDir;


public String getDestination() 
    return destination;


public void setDestination(String destination) 
    this.destination = destination;


public String getActiveMqUrl() 
    return activeMqUrl;


public void setActiveMqUrl(String activeMqUrl) 
    this.activeMqUrl = activeMqUrl;

【讨论】:

【参考方案8】:

我最终使用与正在编写静态代码块的类关联的 getResourceAsStream() 函数完成了此操作。

//associate Property and ImputStream imports
public class A 
    static Properties p;
    static 
      p = new Properties();
      try 
          InputStream in = A.class.getResourceAsStream("filename.properties");
          p.load(in);
       catch (FileNotFoundException e) 
        System.out.println("FileNotFoundException");
        e.printStackTrace();
       catch (IOException e) 
        System.out.println("IOException");
        e.printStackTrace();
      
    
    .
    .
    .

【讨论】:

以上是关于在静态初始化块中加载 java 属性的主要内容,如果未能解决你的问题,请参考以下文章

java创建对象的初始化过程

java类加载顺序

java 静态代码块 代码块 构造函数 静态成员变量 成员变量的初始化顺序

java对象的初始化过程和创建对象的几种方式

Java中加载properties配置文件的几种方式

Java类中各个成员初始化顺序