CDI框架笔记-weld reference中文翻译(二)

如需转载,请注明出处,谢谢http://equalxx.iteye.com/

这次代码格式调整有点凌乱

 

Chapter 1.Introduction 介绍

你现在是不是特别想开始写你的第一个bean了?或者你很犹豫,不知道CDI规范有什么地方会很难。别急,其实你可能已经写过成千上百个bean了,CDI只是让你用它们更简单地创建一个应用!

 

1.1  what is a bean 什么是bean

bean就是你想的那样。也就现在它在容器环境中有了定义,在java EE 6之前,在javaEE平台上术语”bean”没有明确的定义。当然,我们已经把web和企业级应用里面的java类叫做bean很多年了。甚至在javaEE规范里有好几种不同的叫做bean的东西,这其中包括EJB beanJSF托管bean。同时,其他的第三方框架,比如SpringSeam,介绍了他们自己对bean的理解。我们缺一个官方公共定义。

 

最终Java EE 6Managed Bean规范中给出了bean的官方定义。Bean被定义为具有最小编程限制的容器管理对象,在某种情形下被称为POJOPlain Old Java Object)。他们提供少量基本服务,比如资源注入,生命周期回调,以及拦截器。这些规范,比如EJBCDI,都建立在此基础之上。但是,最终,这些bean和轻量级组件模型都会统一起来,在不同JavaEE平台上保持一致。

 

大多时候(除了很少的例外情形),构造器没有参数(或一个构造器被@Inject标注)的具体类被当做bean。这包括了所有的JavaBean和所有EJB会话BeanEJB Session Bean)。如果你已经写过JavaBeanEJBbean的话,相当于已经接触过bean了,不需要在此之上多添加什么特别的配置。你之前每天写的bean到目前为止还没有用到CDI规范里的新服务,但你现在可以试着利用CDI对任何一个bean进行操作:允许容器创建和销毁bean的实例,并将它们与指定的上下文相关联,将它们注入到其他bean中,在EL表达式中使用它们,用限定的注释去标注,甚至给他们添加拦截器和装饰器——这并不需要你修改现有的代码,最多就是加点注释。现在就让我们来创建你的第一个用CDI生成的bean吧。

 

1.2   Getting our feet wet 试水

 

假设我们有两个现有的Java类,我们已经在各种应用里用了很多年了。第一个类是把一个字符串转换成句子list

        

public class SentenceParser {
      public List<String> parse(String text) { ... }
}

 
 

 

第二个类是一个供外部系统前端调用的无状态会话bean,功能是将句子从一种语言翻译成另一种语言:

 

@Stateless
public class SentenceTranslator implements Translator {
      public String translate(String sentence) { ... }
}

 

 

其中TranslatorEJB本地接口:

 

@Local
public interface Translator {
public String translate(String sentence);
}

 

 

让我们写一个bean,翻译整个文本:

public class TextTranslator {
private SentenceParser sentenceParser;
private Translator sentenceTranslator;
@Inject
TextTranslator(SentenceParser sentenceParser, Translator sentenceTranslator) {
this.sentenceParser = sentenceParser;
this.sentenceTranslator = sentenceTranslator;
}
public String translate(String text) {
StringBuilder sb = new StringBuilder();
for (String sentence: sentenceParser.parse(text)) {
sb.append(sentenceTranslator.translate(sentence));
}
return sb.toString();
}
}

 

 

但等等,没有无参数构造器的TextTranslator是否仍然是个bean?如果你还记得的话,一个类没有无参构造器,但如果有@Inject注解的话,它仍然是个bean

 

正如你所想,@Inject和依赖注入有关!@Inject适用于bean的构造器或者方法,然后容器在初始化的时候调用这些构造器或者方法。容器也可以通过这些构造器和方法的参数来注入其他bean

 

我们可以获得TextTranslator的实例通过将其注入到一个bean构造函数、方法、域中,或是一个JavaEE组件类的域或方法(如servlet)。容器选择被注入的对象是通过注入地方的类型,而不是域、方法或者参数的名称。

 

让我们来创建一个通过域注入来获得TextTranslator实例的UI Controller bean吧,用来翻译用户输入的文本。

 

@Named @RequestScoped
public class TranslateController {
@Inject TextTranslator textTranslator;
private String inputText;
private String translation;
// JSF action method, perhaps
public void translate() {
translation = textTranslator.translate(inputText);
}
public String getInputText() {
return inputText;
}
public void setInputText(String text) {
this.inputText = text;
}
public String getTranslation() {
return translation;
}
}

 

 

小贴士:

注意这个Controller是被标注了request-scopednamed的。因为现在web应用里同时用这俩注释非常常见,所以CDI里有个内置的注解@Model,如果用了@Model,就相当于创建了一个@request-scope,@Named bean

 

另外,我们也可以通过编程方式用bean的类型作为参数,从一个被注入的实例的实例获取一个TextTranslator实例,语言说起来有点鸡肋,看代码吧:

import javax.enterprise.inject.Instance;
import javax.inject.Inject;
....
@Inject Instance<TextTranslator> textTranslatorInstance;
...
public void translate() {
textTranslatorInstance.get().translate(inputText);
}

 

 

请注意没必要为了把一个bean注入到另一个bean而去写gettersetter方法。CDI可以直接访问一个被注入的域(甚至它是私有的),这样可以少些无用代码。域的名字可以任意命名,它决定了什么会被注入。

 

在系统初始化期间,容器必须验证注入的类的存在。在我们的例子中,如果没有Translator的实现方法(如果SentenceTranslator EJB没有加载),容器会通知我们这里有个问题依赖(unsatisfied

dependency)。如果有多个Translator的实现类,容器会通知我们依赖模糊(ambiguous dependency)。

 

在我们深入细节以前,让我们先停下来检查一下bean的结构。bean的哪方面最重要,是什么让它最重要。所以与其给你看bean的例子,我们将要找出是什么组成了一个bean

 

如需转载,请注明出处,谢谢http://equalxx.iteye.com/

 

 

展开阅读全文

没有更多推荐了,返回首页