Java EE 6 has three different ways of defining “beans” that are “managed” in one way or another. Here is a quick recap.
JSF 2.0引入了注释,避免声明在xml:
@javax.faces.bean.ManagedBean(name="user") @javax.faces.bean.SessionScoped public class UserBean implements Serializable { ... }
XML配置如下:
<managed-bean> <managed-bean-name>user</managed-bean-name> <managed-bean-class>com.corejsf.UserBean</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> </managed-bean>There is a second annotation for a rudimentary dependency injection mechanism:
public class EditBean { @javax.faces.bean.ManagedProperty(value="#{user}") private UserBean currentUser; }ManagedProperty的使用必须由set方法.(必须提供get/set)
@javax.annotation.ManagedBean("user") public class UserBean ...then you can construct an instance by making a JNDI lookup for java : module / user . But there is no interaction with an expression language, and there is no notion of scopes. So, perhaps this kind of managed bean isn't going to see a lot of love.
In an EE 6 container, you can use JSR 299 “contexts and dependency injection” (CDI), like this:
@javax.inject.Named("user") @javax.enterprise.context.SessionScoped public class UserBean implements Serializable { ... }
Now you refer to the bean as #{user} in JSF, just like you would with JSF managed beans.
If you try this out, remember to put an empty beans.xml into web/WEB-INF to trigger the CDI implementation. This works today with GlassFish v3.
What is the advantage? Well, first off, @Named("user") is shorter than @ManagedBean(name="user"), so you are doing your part alleviating the global pixel shortage.
The advocates of CDI will tell you that they offer facilities for managing beans that go far beyond what JSF has to offer, and that is certainly true. For example, injection works with types, not EL expressions. You would use
@Inject private UserBean currentUser;
Then the CDI implementation automatically injects the UserBean of the appropriate scope. You use annotations (which you define) to control this process, such as
@Inject @LoggedIn private UserBean currentUser;
I won't go into detail here. See the documentation of Weld, the CDI reference implementation, which is very well written. For a quick intro, check outthis blog by Roger Kitain.
Dependency injection is all good and well, but here is a more immediate “selling point” for a JSF programmer. CDI supports the usual request, session, and application scope, but it also provides a conversation scope, a scope whose lifetime is controlled by the application. That's a sorely needed feature to deal with two separate problems: session bloat and multiple browser windows. Again, the Weld documentation describes this quite nicely.
So, should we ditch @javax.faces.bean.ManagedBean before too many people get used to it? If you deploy in an EE 6 container, then there is really no reason to use @ManagedBean. Just use @Named and start using CDI—it's there, so why not take advantage of it? If you use Tomcat or another servlet runner, you can also get CDI by adding the Weld implementation to your web app. According to a recent conversation on the jsr-314-open mailing list (which, sadly, doesn't seem to be archived), Spring 3.0 supports @Named as well, so that seems to be the way to go for consistent examples.
On the flip side, IDE support isn't quite there yet (see this bug—please vote for it), and there will always be some people who will want to use Tomcat without any additional libraries.
Why do I care? We have a very short window for replacing all @ManagedBean with @Named before the 3rd edition of Core JSF goes to print, and I wonder whether we should do it. Please comment! (But please, no flame wars on JSF or CDI—there is a better forum for those :-))