该文档指出:
@PostConstruct 注释可用于添加在完成所有注入时调用的方法:
在您提供的示例代码中,文档谈到的“注入”是您使用注释注释的字段@Inject
。
当 Sling 模型被实例化时,这些字段将被 Sling “注入”。这意味着您不必自己设置这些字段,但 Sling 会处理它。这也称为依赖注入。
回到您的问题:一旦 Sling 注入了所有这些字段,@PostConstruct
将调用带有注释的方法。通常,开发人员使用此方法对 Sling 模型进行进一步初始化。
整个过程是这样的:
- Sling 创建模型的新实例(例如
new MyModelTest()
)。
- Sling 注入您声明的所有依赖项(请参阅
@Inject
注释)。
- Sling 将调用带有
@PostConstruct
注解的方法。
@PostConstruct
注释基本上是构造函数的替代品。如果你要为你的模型编写一个构造函数,你会注意到当构造函数被调用时,所有带有@Inject
注释的字段都还没有设置。如果您尝试对这些字段进行进一步初始化,您将获得一个NullPointerException
.
这就是@PostConstruct
引入注解的原因。它允许您进行通常在构造函数中进行的进一步初始化。
附加说明
将依赖项注入字段称为“字段注入”。还有另一种方法可以通过构造函数注入这些依赖项。这称为“构造函数注入”。
就个人而言,我喜欢尽可能将构造函数注入与 Sling 模型一起使用。使用构造函数注入有助于提高模型的不变性,有助于减少状态并提高可测试性。这是您通常应该在代码中争取的东西。
您的代码示例将与构造函数注入如下:
@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
and out
( new MyModelTest(mockLogger, mockOut)
) 的模拟来创建实例。如果您要使用字段注入,则必须使用反射,这通常不是您想要在代码中执行的操作。尽管不得不说 Sling 项目包含对使用场注入的测试模型的支持。