107

My team is researching dependency injection frameworks and is trying to decide between using Google-Guice and PicoContainer.

We are looking for several things in our framework:

  1. A small code footprint - What I mean by a small code footprint is we don't want to have dependency injection code litter everywhere in our code base. If we need to refactor down the road, we want it to be as easy as possible.
  2. Performance - How much overhead does each framework have when creating and injecting objects?
  3. Ease of use - Is there a large learning curve? Do we have to write mounds of code to get something simple working? We want to have as little configuration as possible.
  4. Community size - Larger communities usually means that a project will continue to be maintained. We don't want to use a framework and have to fix our own bugs ;) Also any questions we have along the way can (hopefully) be answered by the framework's developer/user community .

Comparisons of the two frameworks against the listed criteria would be greatly appreciated. Any personal experiences that help to compare the two would also be extremely helpful.

Disclaimer: I'm fairly new to dependency injection so excuse my noob-ness if I asked a question that isn't pertinent to this discussion.

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487
austen
  • 3,314
  • 3
  • 25
  • 26
  • Update: You might also want to consider [CDI 2.0 – Contexts & Dependency Injection for Java](http://cdi-spec.org). Standardized in [JSR 365](https://jcp.org/en/jsr/detail?id=365) as of 2017-04. – Basil Bourque May 14 '17 at 07:24
  • Here much later, also Dagger2 should be mentioned which does the magic at compile time, not runtime, ensuring that code will run. – Thorbjørn Ravn Andersen May 20 '22 at 19:10

6 Answers6

121

You may want to include Spring in your list of Dependency Injection frameworks you are considering. Here are some answers to your questions:

Coupling to the framework

Pico - Pico tends to discourage setter injection but other than that, your classes don't need to know about Pico. It's only the wiring that needs to know (true for all DI frameworks).

Guice - Guice now supports the standard JSR 330 annotations, so you do not need Guice specific annotations in your code anymore. Spring also supports these standard annotations. The argument that the Guice guys use is that without a Guice annotation processor running, these shouldn't have an impact if you decide to use a different framework.

Spring - Spring aims to allow you to avoid any mention of the Spring framework in your code. Because they do have a lot of other helpers / utilities etc. the temptation is pretty strong to depend on Spring code, though.

Performance

Pico - I'm not too familiar with the speed characteristics of Pico

Guice - Guice was designed to be fast and the comparison mentioned in the reference has some numbers. Certainly if speed is a primary consideration either using Guice or wiring by hand should be considered

Spring - Spring can be slow. There has been work to make it faster and using the JavaConfig library should speed things up.

Ease of use

Pico - Simple to configure. Pico can make some autowire decisions for you. Not clear how it scales to very large projects.

Guice - Simple to configure, you just add annotations and inherit from AbstractModule to bind things together. Scales well to large projects as configuration is kept to a minimum.

Spring - Relatively easy to configure but most examples use Spring XML as the method for configuration. Spring XML files can become very large and complex over time and take time to load. Consider using a mix of Spring and hand cranked Dependency Injection to overcome this.

Community Size

Pico - Small

Guice - Medium

Spring - Large

Experience

Pico - I haven't had much experience with Pico but it is not a widely used framework so it will be harder finding resources.

Guice - Guice is a popular framework and its focus on speed is welcome when you've got a large project that you're restarting a lot in development. I have a concern about the distributed nature of the configuration i.e. it's not easy to see how our whole application is put together. It's a bit like AOP in this respect.

Spring - Spring is usually my default choice. That said, the XML can become cumbersome and the resulting slowdown annoying. I often end up using a combination of hand crafted Dependency Injection and Spring. When you actually need XML based configuration, Spring XML is quite good. Spring also put a lot of effort into making other frameworks more Dependency Injection friendly which can be useful because they often use best practice when doing so (JMS, ORM, OXM, MVC etc.).

References

Community
  • 1
  • 1
Jamie McCrindle
  • 9,114
  • 6
  • 43
  • 48
  • 1
    What I learned (from someone else rather than from using it myself) is that PicoContainer is more light weight than Guice. Also, looking though the PicoContainer doc it also seems to be simpler to use. It will search for dependencies in constructors itself and you don’t need to specify which constructor to use. It just uses a matching one. – Kissaki Oct 26 '10 at 10:59
  • 2
    Yep, I'm big on PicoContainer now myself. It's just a such a "keep it simple", yet working solution, I can't help but look at Spring as bloated and outdated nowadays. Guice is also nice (and has a good backer w/Google), but I *believe* Pico also has more features/flexibility, being older. It's good to see nice alternatives to nasty xml configuration! – Manius Dec 21 '10 at 03:10
  • Just my opinion: I switched from Pico to Guice because I felt Guice was easier to use. Adding annotations to components increases dependencies, but that wasn't a big factor for us as Guice is basically two jars. On the plus side, having @Inject on the constructors makes the other developers aware that the object is a component. That said, I don't think there is anything *wrong* with Pico. I just found Guice a little easier to use. – Joshua Davis Jan 22 '11 at 20:34
  • 1
    I use pico in a number of very large (and heavy-use) projects (hundreds of component types defined in each container), and used most all of its various features, and couldn't be happier with it. – jhouse Feb 02 '11 at 21:04
  • 2
    I just made a simple performance test with Guice/Spring/PicoContainer - Guice and PicoContainer are fairly similar. In some cases Guice was a little faster. Spring was very slow in all cases. – Joshua Davis Jun 25 '11 at 05:20
27

The answer put up by jamie.mccrindle is actually pretty good, but I'm left confused why Spring is the default choice when it's pretty clear that superior alternatives (both Pico and Guice) are available. IMO Spring's popularity has reached it's peak and now it's currently living off the generated hype (along with all the other "me too" Spring sub projects looking to ride the Spring bandwagon).

Spring's only real advantage is community size (and quite frankly, due to the size and complexity, it's needed), but Pico and Guice don't need a huge community because their solution is much cleaner, more organized, and more elegant. Pico seems more flexible than Guice (you can use annotations in Pico, or not--it's extremely efficient). (Edit: Meant to say it's extremely flexible, not that it isn't also efficient.)

Pico's tiny size and lack of dependencies is a MAJOR win which shouldn't be understated. How many megs do you need to download to use Spring now? It's a kludgy-mess of huge jar files, with all it's dependencies. Intuitively thinking, such an efficient and "small" solution should scale and perform better than something like Spring. Is Spring's bloat really going to make it scale better? Is this bizarro world? I wouldn't make assumptions that Spring is "more scalable" until that's proven (and explained).

Sometimes creating something good (Pico/Guice) and then keeping your HANDS OFF of it instead of adding bloat and kitchen sink features with endless new versions really does work out...

Manius
  • 3,594
  • 3
  • 34
  • 44
  • 1
    Care to say _why_ Pico and Guice are superior to Spring? – Thorbjørn Ravn Andersen Jan 25 '13 at 07:24
  • 4
    I thought I did - basically, they do DI just as well, they're simpler/smaller/cleaner, and no or few dependencies. That's not to say that Spring *never* makes sense (I'm sure there are cases), all I'm saying is that simpler is better if your requirements are being met. And for a very large number of projects, small support libs are all you need. – Manius Aug 13 '13 at 16:53
  • Funny this keeps getting upvotes 12 years later, and I don't even fully agree with it anymore. Not to mention Pico is too neglected to bother with anymore at this point; which is a shame, it was a nice simple, focused tool while it lasted. To update for 2022, since we now have Spring Boot which I believe first came out about 4 years after this answer, things are very different. I generally default to Spring unless I need something very lightweight. – Manius May 07 '22 at 18:48
13

NOTE: This is more of a comment/rant than an answer

PicoContainer is great. I'd switch back to it if they'd just fix their web sites. It's really confusing now:

I'm using Guice 2.x now, even though it's bigger, and it has fewer features. It was just much easier to find the documentation, and it's user group is very active. However, if the direction of Guice 3 is any indication, it looks like Guice is starting to bloat, just like Spring did way back in the early days.

Update: I posted a comment to the Pico Container folks and they've made some improvements to the web site. Much better now!

MiB
  • 575
  • 2
  • 10
  • 26
Joshua Davis
  • 3,499
  • 1
  • 26
  • 29
3

It is a old question but today you can consider Dagger (https://github.com/square/dagger) in your Android App project. Dagger does code generation on compilation time. So you get a shorter startup time and less memory usage on execution time.

A.C.Andreani
  • 31
  • 1
  • 3
  • I like Dagger, but it seems like there isn't a Gradle plugin in the public repos for non-Android projects yet (i.e. a Gradle plugin for 'regular' java projects). I'd consider it for Java projects if there was a plugin in the public repos. – Joshua Davis Jun 19 '14 at 22:28
3

If you're after a minimalistic DI container, you can check out Feather. Vanilla JSR-330 DI functionality only, but quite good in terms of footprint (16K, no dependencies) and performance. Works on android.

Cellux
  • 71
  • 2
  • Hey, Feather is awesome! I've used it to implement a [DI plugin](https://github.com/actframework/act-feather) for [ActFramework](https://github.com/actframework/actframework). I did a few updates, e.g. automatically call injectFields if needed, and support to injection listener, let me know if you want me to send back a pull request – Gelin Luo Mar 27 '16 at 09:15
  • @green I see you've moved to Genie. Could you please share your experiences of using Feather? – beerBear Dec 01 '16 at 09:54
  • 1
    @beerBear Feather is very lightweight and very easy to use in most of the DI use cases. However since I am working on a fullstack MVC framework, I need a solution that implement full JSR330 spec. That's why I moved to Genie – Gelin Luo Dec 05 '16 at 08:03
  • @green I appreciate your post of the explanation to get a better understanding. – beerBear Jan 16 '17 at 09:32
0

Although I do like PicoContainer for it's simplicity and it's lack of dependencies. I would recommend using CDI instead because it is part of the Java EE standard so you have no vendor lock-in.

In terms of intrusiveness, it's main problem is the requirement of a container and the use of a relatively empty META-INF/beans.xml file (needed to indicate that the jar is using CDI) and the use of annotations (though they are standard)

The lightweight CDI container I use for my own projects is Apache Open Web Beans. Though it took a while to figure out how to create a simple app (unlike Pico) which looks like this.

public static void main(final String[] args) {
    final ContainerLifecycle lifecycle = WebBeansContext.currentInstance()
            .getService(ContainerLifecycle.class);
    lifecycle.startApplication(null);

    final BeanManager beanManager = lifecycle.getBeanManager();
    // replace Tester with your start up class
    final Bean<?> bean = beanManager.getBeans(Tester.class).iterator()
            .next();

    final Tester b = (Tester) lifecycle.getBeanManager().getReference(bean,
            Tester.class, beanManager.createCreationalContext(bean));
    b.doInit();
}
Archimedes Trajano
  • 35,625
  • 19
  • 175
  • 265
  • 2
    If you stick with JSR-330 in your library code, you can keep the container specific code to a minimum. – Thorbjørn Ravn Andersen Jan 21 '13 at 13:56
  • You still need container specific code in your automated testing. Though it does not mean you would have container specific code in your actual code (and you shouldn't anyway unless you plan to run your own "main" which in one app I wrote for myself I did. – Archimedes Trajano Feb 03 '13 at 08:06