在AEM SlingModel概念中@postconstructor有什么用?

时间:2018-06-14 02:10:17

标签: aem sling-models

我在@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");
    }
}

1 个答案:

答案 0 :(得分:1)

documentation州:

  

@PostConstruct注释可用于添加在完成所有注入后调用的方法:

在示例代码中,您提供了“注入”,文档说明了,是您使用@Inject注释注释的字段。

当Sling模型被实例化时,这些字段将被Sling“注入”。这意味着您不必自己设置这些字段,但Sling会处理它。这也称为Dependency Injection

回到你的问题:一旦所有这些字段被Sling注入,将调用带有@PostConstruct注释的方法。通常,开发人员使用此方法进一步初始化Sling模型。

整个过程如下:

  1. Sling会为您的模型创建一个新实例(例如new MyModelTest())。
  2. Sling会注入您声明的所有依赖项(请参阅@Inject注释)。
  3. Sling将调用使用@PostConstruct注释注释的方法。
  4. @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;
        }
    }
    

    类字段loggerout现在可以设置final,这会增加不变性,因为它们不能再被更改了。

    当您注入服务等以进行进一步初始化时,您可以将结果存储在final类字段中,而不是将服务引用本身作为类字段注入。这些参考 - 理论上 - 可以指向不存在的服务(服务可以在OSGi中进出)。例如:如果您有一个存储所需配置的服务,您可以只读取您感兴趣的配置值,然后将其存储在类字段中。

    最后但并非最不重要的是可测试性得到了改进,因为您现在可以通过调用new MyModelTest([...])并传递模拟loggeroutnew MyModelTest(mockLogger, mockOut))来创建实例。如果您要使用字段注入,则必须使用reflection,这通常不是您想要在代码中执行的操作。虽然必须说Sling项目包含对使用现场注入的测试模型的支持。