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

Reply via email to