从static变量初始化到Spring/Spring boot的工具类静态变量注入
2017-04-10 10:04
423 查看
写这篇博文,要从
在执行调用的时候就会报错了!那原因是什么呢?
原因还是很简单的,在调用Domain静态方法时,由于两个变量都是静态变量,不会对它进行赋值,但会对变量按顺序进行初始化。所以先给domain初始化,这个时候调用私有构造函数,函数内已经用到了domainMap,而这个变量还没有初始化,进而抛出了没有初始化类的异常。
想要解决这个异常,两种方案。
把domain和domainMap的变量声明位置调换,这样在调用私有构造函数时domainMap已经初始化了。
将domain的构造函数公有化,并使外部调用来初始化,而不是声明时即初始化。当然这样并不符合工具类的使用方便,会造成浪费内存等后果。
之所以举上面这个例子,是因为它的构造很像工具类。
首先你得明白什么是工具类,简单来说它是一种可以不用初始化对象而直接调用其静态方法而达到某一些功能的以Utils或Helper结尾的类。说到这里,要声明一下,并不是所有的静态类都是推荐使用的,使用静态类的过程往往只是为了阅读方便和调用简单,但却不知会增加程序的耦合度,破坏设计模式等缺点。这里贴一篇文章写的很不错:如何摆脱工具类。
而我们最终的问题是,如何在工具类中初始化赋值静态属性呢。项目环境是在spring框架下,举个例子:
当外部想要调用
怎么去注入呢?
采用间接注入方式
也可以使用在Spring Boot中使用 @ConfigurationProperties 注解 给出的注解方式,是针对spring-boot的。
将静态参数用beans提取,以键值对形式存储,在工具类中直接调用
配置
应用
其中
如果你不想提取bean,也可以直接读取file.
待你完善
期待有更好的方法一起交流讨论。
java.lang.ExceptionInInitializerError的原因
java.lang.ExceptionInInitializerError
in Connection Factory
java.lang.ExceptionInInitializerError这个报错开始。简单的看上去,这是一个类初始化异常报错。但事实上并不是这样,这是由于调用某个
static变量属性时而该属性没有初始化而导致的错误,所以,在
debug模式下,你第二次再尝试调用操作
static属性的方法时,可能就会抛出一个空指针异常了。据听请看这段代码。
Domain.java
public class Domain { private static Domain domain = new Domain(); private static Map<String,String> domainMap = new HashMap<String ,String>(); private Domain() { domainMap.put("isTrue","true"); } public static Domain getInstance() { return domain; } }
TestDomain.java
public class TestDomain { public static void main(String[] args) { String domainString = Domain.getInstance().toString(); System.out.println(domainString); } }
在执行调用的时候就会报错了!那原因是什么呢?
原因还是很简单的,在调用Domain静态方法时,由于两个变量都是静态变量,不会对它进行赋值,但会对变量按顺序进行初始化。所以先给domain初始化,这个时候调用私有构造函数,函数内已经用到了domainMap,而这个变量还没有初始化,进而抛出了没有初始化类的异常。
想要解决这个异常,两种方案。
把domain和domainMap的变量声明位置调换,这样在调用私有构造函数时domainMap已经初始化了。
将domain的构造函数公有化,并使外部调用来初始化,而不是声明时即初始化。当然这样并不符合工具类的使用方便,会造成浪费内存等后果。
渐进
之所以举上面这个例子,是因为它的构造很像工具类。首先你得明白什么是工具类,简单来说它是一种可以不用初始化对象而直接调用其静态方法而达到某一些功能的以Utils或Helper结尾的类。说到这里,要声明一下,并不是所有的静态类都是推荐使用的,使用静态类的过程往往只是为了阅读方便和调用简单,但却不知会增加程序的耦合度,破坏设计模式等缺点。这里贴一篇文章写的很不错:如何摆脱工具类。
而我们最终的问题是,如何在工具类中初始化赋值静态属性呢。项目环境是在spring框架下,举个例子:
XXXProperties.java
public class XXXProperties { private String staticParam1; private String staticParam2; public String getStaticParam1() { return staticParam1; } public void setStaticParam1(String staticParam1) { this.staticParam1 = staticParam1; } public String getStaticParam2() { return staticParam2; } public void setStaticParam2(String staticParam2) { this.staticParam2 = staticParam2; } }
XXUtils.java
public class XXUtils { @Autowired //静态变量通过spring并不能直接注入,所以这样是会报错的 private static XXXProperties xxxProperties; private static String do() { String xxxPropertiesSize = xxxProperties.getSize(); return xxxPropertiesSize; } }
当外部想要调用
XXUtils的
do()时,发现xxxProperties并没有注入值,而我们去调用时,程序也自然会抛出文章开始说的异常。
怎么去注入呢?
方案
采用间接注入方式//可以换成@Configuration,与@Inject配合使用 @Component public class XXUtils { //可以换成@Inject @Resource private XXXProperties xxxPropertiesAutowired; private static XXXProperties xxxProperties; @PostConstruct public void init() { this.xxxPropertiesAutowired = xxxProperties; } }
也可以使用在Spring Boot中使用 @ConfigurationProperties 注解 给出的注解方式,是针对spring-boot的。
将静态参数用beans提取,以键值对形式存储,在工具类中直接调用
配置
应用
其中
public class org.springframework.beans.factory.config.PropertyPlaceholderConfigurer extends org.springframework.beans.factory.config.PlaceholderConfigurerSupport
如果你不想提取bean,也可以直接读取file.
public class XMLConfig { private static final Logger logger = Logger.getLogger(XMLConfig.class); public static final String FILEPATH = "xmlconf.properties"; public static long fileLastModified = 0; //属性文件xmlconf.properties中对应的各个键值对 public static HashMap<String, String> paramsMap = new HashMap<String, String>(); public static HashMap<String, String> loadProperties(String file) { HashMap<String, String> map = new HashMap<String, String>(); InputStream in = null; Properties p = new Properties(); try { in = new BufferedInputStream(new FileInputStream(file)); p.load(in); } catch (FileNotFoundException e) { logger.error(file + " is not exists!"); } catch (IOException e) { logger.error("IOException when load " + file); } finally { if (in != null) { try { in.close(); } catch (IOException e) { logger.error("Close IO error!"); } } } Set<Entry<Object, Object>> set = p.entrySet(); Iterator<Entry<Object, Object>> it = set.iterator(); while (it.hasNext()) { Entry<Object, Object> entry = it.next(); String key = (String) entry.getKey(); String value = (String) entry.getValue(); logger.debug(key + "=" + value); // System.out.println(key + "=" + value); if (key != null && value != null) { map.put(key.trim(), value.trim()); } } return map; } }
待你完善
期待有更好的方法一起交流讨论。
参考
java.lang.ExceptionInInitializerError的原因java.lang.ExceptionInInitializerError
in Connection Factory
相关文章推荐
- Spring不能注入Static变量的原因及Spring注入静态变量
- SpringBoot如何优雅的将静态资源配置注入到工具类中
- spring boot: Bean的初始化和销毁 (一般注入说明(三) AnnotationConfigApplicationContext容器 JSR250注解)
- Spring不能直接@autowired注入Static变量
- SpringBoot中静态变量注入
- spring boot 两种方式注入到静态工具类里面
- Java学习笔记38:通过Spring Bean 注入static变量,来设计一套适合测试,开发,生产环境的配置项
- Spring boot工具类静态属性注入及多环境配置详解
- spring 注入变量不可以改成静态变量
- spring与springboot中,如何在static方法里用@Autowire或者@Resource注入的属性
- Spring boot中使用工具类 无需注入获取.yml中的值
- springboot @value注入static对象 与 application.properties 与 pom.xml 取值
- 参考 - spring boot 静态变量注入值
- springboot中静态变量值的注入及子项目间的profile的设置
- Spring boot中使用工具类 无需注入获取.yml中的值
- 关于Spring/SpringBoot在静态工具类中注入Service的解决方案
- spring 依赖注入到static工具类
- 【转】Java类的初始化顺序 (静态变量、静态初始化块、变量、初始化块、构造器)
- C++函数中的static变量初始化及析构顺序
- static 变量和static 构造函数 以及对象初始化顺序