java类。newInstance创建所有属性都为空的对象
我有一个类需要动态初始化,如下所示:
void doSth(classsuffix) throws Exception {
String classname = "org.test.classname" + classsuffix; // classsuffix is dynamic
Class<?> clazz;
clazz = Class.forName(classname);
TestInterface test = (TestInterface) clazz.newInstance();
test.doStuff();
}
与示例类(遵循相同模式的多个类之一)配对:
public class classnameOne implements TestInterface {
@Inject
private Logger log;
// ...
@Override
public void doStuff() {
// Do stuff
log.info("done");
}
}
问题是classnameOne
类中的log
在初始化时将是null
,因此log.info()
调用将抛出NullPointerException
但是我需要那个记录器,所以在创建带有newInstance()
的类时,有没有可能初始化注入的属性
或者有没有其他基于字符串动态创建对象的可能性
# 1 楼答案
首先,你正在使用CDI,所以你需要一个bean。xml文件必须在META-INF中,即使该文件是完全空的,否则它将无法工作
例如:
然后,你想注入你的记录器,但你需要一个制作人,一个简单的方法是:
向logger属性添加transient关键字也很重要,因为products无法生成不可序列化的实例
有趣的阅读:
更新
如果您坚持使用Class::newInstance()方法,那么您可以通过以下方式进行:
向TestInterface添加一个方法,该方法将返回TestInterface对象并将其命名为getInstance()
在每个类中实现该方法
只需在以前的代码中添加使用构造函数检索具体实例的新方法(这将进行适当的依赖项注入):
它不漂亮,而且闻起来很香,但它确实能满足你的需求
PD:inject注释不适用于构造函数::newInstance(),也不适用于类::newInstance(),所以我想这将是最接近您想要做的事情
# 2 楼答案
AutowireCapableBeanFactory
可能对你的问题有帮助,但请注意,这种方法有点臭,不建议用于典型用例。请参阅此链接:https://stackoverflow.com/a/52355649/6223518
# 3 楼答案
我找到了更好的解决办法
使用CDI。当前()对象:
可供参考的示例类:
有了这个解决方案,就不需要对现有的类或类似的东西进行任何更改
旧版本
我能找到的最佳解决方案是:
创建所有可用类的集合:
并将其注入到想要动态类的类中:
可供参考的示例类:
老实说,我认为这是最好的解决方案,因为它不会改变任何子类,而且维护起来非常简单(只需在
ClassnameCollection
类中添加一个新的Inject
)