+1
On Thu, Apr 8, 2010 at 15:42, Vincent Massol <vincent(a)massol.net> wrote:
On Apr 8, 2010, at 3:17 PM, Sergiu Dumitriu wrote:
On 04/08/2010 02:21 PM, Vincent Massol wrote:
> Hi devs,
>
> Since the JSR330 is now accepted as final and thus as a standard, I'd
like
to propose that we modify our component annotations to use it.
+1
> Rationale
> ========
>
> The advantages of using it are:
> * Be standard, ie:
> ** Our components will be able to be re-used by injectors other than
ours
(Guice for example)
> ** Since IDEs will support JSR330 they'll
be able to offer features for
our code (auto complete, graph, etc), for ex
http://blogs.jetbrains.com/idea/tag/dependency-injection/
>
> Proposed Changes
> ===============
>
> Note: JSR330 doesn't specify how components should be bound, hence the
need to keep xwiki-specific metadata for the bindings.
* @Component and @ComponentRole stay unchanged
Except that the package changes, right?
Nope, we keep our annotations for the bindings part since it's not part of
the JSR330 spec.
> * Deprecate @Requirement, replaced by
@Inject
> * Use @Named or application-specific annotations (based on @Qualifier)
instead
of hints specified in the @Requirement annotation
> * Add new @Role(Class) to specify a
dependency role in the case of
collections (since generics are not available using
reflection in Java)
@Role will kind of break the "be standard, so supported by other
injectors" motivation. Are you sure there's no way for doing this? Maybe
we should have commented during the standardization process.
Not really, binding is out of scope for JSR330. Here's what they say:
"
This package provides dependency injection annotations that enable portable
classes, but it leaves external dependency configuration up to the injector
implementation. Programmers annotate constructors, methods, and fields to
advertise their injectability (constructor injection is demonstrated in the
examples above). A dependency injector identifies a class's dependencies by
inspecting these annotations, and injects the dependencies at run time.
Moreover, the injector can verify that all dependencies have been satisfied
atbuild time. A service locator, by contrast, cannot detect unsatisfied
dependencies until run time.
Injector implementations can take many forms. An injector could configure
itself using XML, annotations, a DSL (domain-specific language), or even
plain Java code. An injector could rely on reflection or code generation. An
injector that uses compile-time code generation may not even have its own
run time representation. Other injectors may not be able to generate code at
all, neither at compile nor run time. A "container", for some definition,
can be an injector, but this package specification aims to minimize
restrictions on injector implementations.
"
> * Deprecate @InstantiationStrategy, replaced
by @Singleton. We don't
need to introduce any other scope annotations for now.
> * Note that the default scope in the JSR330
spec is "per lookup". Since
our default is singleton, we'll need to
add @Singleton annotations
everywhere we used to not have anything.
This (@Singleton everywhere) is the biggest inconvenience, but we'll
manage.
Yep it'll be a pain.
We also need to update the component tutorial.
Yes, and the Module doc too.
Example
before:
@Component("html")
public class HTMLMacro extends AbstractMacro<HTMLMacroParameters>
{
...
@Requirement
private HTMLCleaner htmlCleaner;
...
@Requirement("xhtmlmacro/1.0")
private PrintRendererFactory xhtmlRendererFactory;
...
@Requirement(role = Transformation.class)
private List<Transformation> transformations = new
ArrayList<Transformation>();
Same example after the change:
@Component("html")
public class HTMLMacro extends AbstractMacro<HTMLMacroParameters>
{
...
@Inject
private HTMLCleaner htmlCleaner;
...
@Inject
@Named("xhtmlmacro/1.0")
private PrintRendererFactory xhtmlRendererFactory;
...
@Inject
@Role(Transformation.class)
private List<Transformation> transformations = new
ArrayList<Transformation>();
Right?
yes (same for Maps).
For the record, note that in Guice the binding is done like this:
bind(new TypeLiteral<Map<GeneticOperator, Double>>() {}).to(...);
See also
http://code.google.com/p/google-guice/source/browse/trunk/src/com/google/in…
Thanks
-Vincent
_______________________________________________
devs mailing list
devs(a)xwiki.org
http://lists.xwiki.org/mailman/listinfo/devs