Dagger 2 has compile-time validation, so why do the scope annotations have RUNTIME
retention? Why are they needed at runtime?
问题:
回答1:
Though I don't know for sure, I'd guess that Scopes necessarily have runtime retention because JSR 330's @Scope
requires scopes to have runtime retention. (@Qualifier
has the same restriction.) Both Dagger 1 and Dagger 2 advertise JSR-330 compatibility, and (as David mentions in the comments) there are plenty of runtime dependency injection solutions that would absolutely require runtime-retained scope annotations.
For Dagger in particular, I can't imagine why they'd actually be read at runtime either, though I suppose some external libraries could make use of the annotation.
Edit from comments + Android multidex caveat
This is not necessarily a problem, legacy or otherwise: Many DI systems configure at runtime and require the annotation. Dagger is notable in that it doesn't, but the spec was not written in a way that allows for runtime retention to be optional. This frees app developers to replace Dagger with a different JSR330 framework like Guice or Spring, and it frees library developers to make DI-compatible tools or frameworks agnostic to whether they are compile-time-configured or runtime-configured. That spec clarity (i.e. without implementation options) and flexibility (compile time or runtime) seems worth the cost of unnecessary annotation retention and the cost of learning.
However, this can be a problem in large Android apps because Android keeps runtime-annotated classes in the main dex by default; older versions of Android fail to load runtime annotations if the annotated class is in a secondary dex. See this bug linked from the keepRuntimeAnnotatedClasses
docs for details. Though you could consider this a Dagger problem because of Dagger's applicability to large Android apps, it's more of a bug with Android annotation handling, for which Dagger would need to diverge from the JSR-330 spec in order to handle itself.