我在@postconstructor
使用时何时可以使用SlingModel
?
@Model(adaptables=SlingHttpServletRequest.class)
public class MyModelTest {
@Inject
private PrintWriter out;
@Inject
@Named("log")
private Logger logger;
@PostConstruct
protected void sayHelloTest() {
logger.info("hello world");
}
}
答案 0 :(得分:1)
@PostConstruct注释可用于添加在完成所有注入后调用的方法:
在示例代码中,您提供了“注入”,文档说明了,是您使用@Inject
注释注释的字段。
当Sling模型被实例化时,这些字段将被Sling“注入”。这意味着您不必自己设置这些字段,但Sling会处理它。这也称为Dependency Injection。
回到你的问题:一旦所有这些字段被Sling注入,将调用带有@PostConstruct
注释的方法。通常,开发人员使用此方法进一步初始化Sling模型。
整个过程如下:
new MyModelTest()
)。@Inject
注释)。@PostConstruct
注释注释的方法。 @PostConstruct
注释基本上是构造函数的替代。如果您要为模型编写构造函数,您会注意到在调用构造函数时,所有具有@Inject
注释的字段尚未设置。如果您尝试使用这些字段进行进一步初始化,则会获得NullPointerException
。
这就是引入@PostConstruct
注释的原因。它允许您进行通常在构造函数中进行的进一步初始化。
将依赖项注入字段称为“字段注入”。还有另一种方法可以通过构造函数注入这些依赖项。这称为“构造函数注入”。
就个人而言,我喜欢在可能的情况下使用Sling Models进行构造函数注入。使用构造函数注入有助于提高模型的不变性,有助于减少状态并提高可测试性。这是您通常应该在代码中努力的事情。
您的代码示例如下所示:构造函数注入:
@Model(adaptables=SlingHttpServletRequest.class)
public class MyModelTest {
private final Logger logger;
private final PrintWriter out;
@Inject
public MyModelTest(
@ScriptVariable @Named("log") final Logger logger,
@ScriptVariable @Named("out") final PrintWriter out
) {
this.logger = logger;
this.out = out;
}
}
类字段logger
和out
现在可以设置final
,这会增加不变性,因为它们不能再被更改了。
当您注入服务等以进行进一步初始化时,您可以将结果存储在final
类字段中,而不是将服务引用本身作为类字段注入。这些参考 - 理论上 - 可以指向不存在的服务(服务可以在OSGi中进出)。例如:如果您有一个存储所需配置的服务,您可以只读取您感兴趣的配置值,然后将其存储在类字段中。
最后但并非最不重要的是可测试性得到了改进,因为您现在可以通过调用new MyModelTest([...])
并传递模拟logger
和out
(new MyModelTest(mockLogger, mockOut)
)来创建实例。如果您要使用字段注入,则必须使用reflection,这通常不是您想要在代码中执行的操作。虽然必须说Sling项目包含对使用现场注入的测试模型的支持。