除了基础部分和高级部分,CDI的第三个主题是整合。
CDI还设计了通过SPI提供集成点到Java EE平台的协同工作的平台之外的技术[在Java EE 6发布后,各种各样的Java EE平台扩展(构建在CDI扩展SPI之上)涌现了出来。]。这SPI CDI定位为便携式扩展和集成现有的框架和技术,作为整合JavaEE生态系统的基础。当然, Java EE平台将永远无法规范世界中所有在Java应用程序开发使用的有趣的技术.
你可能不会永远需要直接使用这些SPI ,但不要无视他们的存在。你可能会间接使用它们,比如你使用第三方扩展,如DeltaSpike 。
你甚至可以使用拦截器绑定消息驱动Bean。
我们可以使用Producer字段和方法准备所有这些资源,用于注入bean:
如果使用CDI,bean.xml是必须要有的.
注意:CDI 1.1 makes use of a new XSD file for beans.xml descriptor: http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd
CDI还设计了通过SPI提供集成点到Java EE平台的协同工作的平台之外的技术[在Java EE 6发布后,各种各样的Java EE平台扩展(构建在CDI扩展SPI之上)涌现了出来。]。这SPI CDI定位为便携式扩展和集成现有的框架和技术,作为整合JavaEE生态系统的基础。当然, Java EE平台将永远无法规范世界中所有在Java应用程序开发使用的有趣的技术.
你可能不会永远需要直接使用这些SPI ,但不要无视他们的存在。你可能会间接使用它们,比如你使用第三方扩展,如DeltaSpike 。
一:Java EE integration
CDI是完全集成到Java EE环境的.1. Built-in beans
在Java EE环境中,容器提供了以下内置Bean,全部用限定符 @Default :- 当前JTA的UserTransaction,
- 标识当前调用者主要的identity(身份ID),
- 默认Bean Validation的 ValidationFactory
- 一个验证器的默认ValidationFactory,
- HttpServletRequest, HttpSession and ServletContext
import javax.enterprise.inject.Produces;
class FacesContextProducer {
@Produces @RequestScoped FacesContext getFacesContext() {
return FacesContext.getCurrentInstance();
}
}
2.Injecting Java EE resources into a bean
所有ManagedBean可以利用的Java EE组件环境注入,可使用 @Resource , @EJB, @PersistenceContext, @PersistenceUnit and @WebServiceRef.。我们已经看到了一些这方面的例子,@Transactional @Interceptor
public class TransactionInterceptor {
@Resource UserTransaction transaction;
@AroundInvoke
public Object manageTransaction(InvocationContext ctx) throws Exception { ... }
}
@SessionScoped
public class Login implements Serializable {
@Inject Credentials credentials;
@PersistenceContext EntityManager userDatabase;
...
}
在Java EE @PostConstruct和@PreDestroy的生命周期回调也支持所有ManagedBean。所有资源注入完成后@PostConstruct方法会被调用。
当然,我们建议组件环境注入是被用来定义CDI资源,并且在应用程序代码中以类型安全的注入。3. Calling a bean from a servlet
从Java EE的一个servlet调用一个Bean也是很容易的.只需用字段或初始化方法注入Bean.如下所示:public class LoginServlet extends HttpServlet {
@Inject Credentials credentials;
@Inject Login login;
//只是示例,实际开发要避免重写Service方法,
//一为了保留HttpServlet默认实现的缓存协商的机制(HTTP 304);
//二就是禁用你没有在servlet中重写的方法,例如post、head等,这样就从一定程度上提高了安全性
@Override
public void service(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
credentials.setUsername(request.getParameter("username")):
credentials.setPassword(request.getParameter("password")):
login.login();
if ( login.isLoggedIn() ) {
response.sendRedirect("/home.jsp");
}
else {
response.sendRedirect("/loginError.jsp");
}
}
}
servlet的实例共享所有传入的线程.
4. Calling a bean from a message-driven bean
CDI注入适用于所有的EJB,甚至他们不是CDI Bean。特别是你可以在消息驱动bean使用CDI注入.你甚至可以使用拦截器绑定消息驱动Bean。
@Transactional
@MessageDriven
public class ProcessOrder implements MessageListener {
@Inject Inventory inventory;
@PersistenceContext EntityManager em;
public void onMessage(Message message) {
...
}
}
请注意,消息驱动bean不能注入@SessionScoped或@ConversationScoped的Bean。只有@RequestScoped和@ApplicationScopedBean可用。
5. JMS endpoints
使用JMS发送消息可能相当复杂,因为你需要处理许多不同的对象。queues方面的Queue,QueueConnectionFactory、QueueConnection QueueSession QueueSender。 topics方面的 topics ,TopicConnectionFactory、TopicConnection TopicSession TopicPublisher。每个对象都有自己的生命周期和线程模型,我们需要仔细处理这些问题, 最好的方式就是让容器控制。我们可以使用Producer字段和方法准备所有这些资源,用于注入bean:
import javax.jms.ConnectionFactory;
import javax.jms.Queue;
public class OrderResources {
@Resource(name="jms/ConnectionFactory")
private ConnectionFactory connectionFactory;
@Resource(name="jms/OrderQueue")
private Queue orderQueue;
@Produces
@Order
public Connection createOrderConnection() throws JMSException {
return connectionFactory.createConnection();
}
public void closeOrderConnection(@Disposes @Order Connection connection)throws JMSException {
connection.close();
}
@Produces
@Order
public Session createOrderSession(@Order Connection connection)throws JMSException {
return connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
}
public void closeOrderSession(@Disposes @Order Session session)throws JMSException {
session.close();
}
@Produces
@Order
public MessageProducer createOrderMessageProducer(@Order Session session)throws JMSException {
return session.createProducer(orderQueue);
}
public void closeOrderMessageProducer(@Disposes @Order MessageProducer producer)throws JMSException {
producer.close();
}
}
使用示例:
@Inject Order order;
@Inject @Order MessageProducer producer;
@Inject @Order Session orderSession;
public void sendMessage() {
MapMessage msg = orderSession.createMapMessage();
msg.setLong("orderId", order.getId());
...
producer.send(msg);
}
注入的JMS对象的生命周期完全由容器控制。
6. Packaging and deployment
CDI没有定义任何特殊的部署类型。您可以打包成JAR文件,EJB JARs或war包.如果使用CDI,bean.xml是必须要有的.
注意:CDI 1.1 makes use of a new XSD file for beans.xml descriptor: http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd
beans.xml文件必须位于:META-INF/beans.xml(jar包),或者,WEB-INF/beans.xml或WEB-INF/classes/META-INF/beans.xml(war包)。
Over.
来源:oschina
链接:https://my.oschina.net/u/214542/blog/266125