Hi, I recently made a change to add a new mechanism for injecting dependencies into tasks. Previously, to inject services into a task instance we were using either:
1. getServices().get(Type) or 2. constructor injection. One downside with #1 is that the approach not declarative, so we can’t figure out statically which services a task is going to use, or when. This is important in order for us to determine things like the possible inputs and outputs of the task, or to do any early validation, or deal with services that require some work to make usable, and so on. Approach #2 addresses this issue (mostly), but has a couple of downsides of its own. Firstly, for good or bad, we currently make the task types public and allow them to be subclassed. This means that the implementation services are exposed to subtypes and we can’t change the set of services without changing the constructor - thereby breaking backwards compatibility. Secondly, approach #2 requires that all the services be created when the task is created, regardless of whether the task or service is ever required. The services are also retained for the entire life of the task object. This has a noticeable impact on performance and heap usage in particular. This was the main motivation for the change. The ‘proper’ solution here is to separate out the configuration and the implementation pieces of a task, and defer creation of the implementation stuff, and the services it needs, until execution time. This will be part of the solution to allow tasks from a given project to execute in parallel. In the meantime, and for legacy tasks, there is a new mechanism to inject services that addresses the downsides of #1 and #2 above. To use this, define a getter annotated with @Inject: @Inject protected MyService getMyService() { … doesn’t matter what goes in here ... } When decorated, this method is replaced with a service lookup. The lookup is lazy, so that the service is not created until the getter is called. This mechanism is considered incubating at this stage. It only works for tasks for now, but would probably be useful for all decorated types (and plugins, which aren’t decorated yet). -- Adam Murdoch Gradle Co-founder http://www.gradle.org VP of Engineering, Gradleware Inc. - Gradle Training, Support, Consulting http://www.gradleware.com Join us for Gradle Summit 2014, June 12th and 13th in Santa Clara, CA: http://www.gradlesummit.com