一、Why?
我们在客户端调用服务端对象的时候,通常需要通过服务器的 JNDI 来查找session bean或MDB。JNDI 查找是把客户端与实际的服务端实现解藕的关键步骤。 但是, 直接使用一个字符串来进行 JNDI 查找并不优雅。有这样几个原因:
· 客户端与服务端必须有一致的基于字符串的名字。 它没有在编译时得到认证或在部署时得到检查。· 从 JNDI 返回的服务对象的类型没有在编译时进行检查, 有可能在运行时出现转换(casting)错误。
· 冗长的查找代码,有着自己的 try-catch 代码块,在应用之间是重复的和杂乱的EJB 3.0,对任何 POJO,提供了一个简单的和优雅的方法来解藕服务对象和资源。
由于以上原因,便有了我们的EJB依赖注入。
二、How?
1.注入Session Bean
注入Session Bean有四种方式:
[1] beanInterface:指被注入属性EJB所实现的接口。
[2] name:被注入Bean在JNDI ENC中注册的名称,不同服务器存在不同的差异.
[3] beanName:指定EJB的名称(如果@Stateless或@Stateful没有设置过name属性,默认为不带包名的类名)
[4] mappedName:被注入EJB的JNDI名,不同服务器存在不同的差异.
举例:通过beanName注入
①本地接口和实现类:
//本地接口 public interface HelloWorld { public String sayHello(String name); } //本地接口实现Bean @Stateless(name="HelloWorld") @Local({HelloWorld.class}) public class HelloWorldBean implements HelloWorld { @Override public String sayHello(String name) { return name+"欢迎使用EJB3.0~~"; } }
②远程接口和实现类:
//远程接口 public interface CallHello { public String sayHello(String name); } //远程接口实现类 @Stateless @Remote({CallHello.class}) public class CallHelloBean implements CallHello { @EJB(name="HelloWorld") // @EJB(mappedName="HelloWorld/local") private HelloWorld helloWorld; @Override public String sayHello(String name) { String result = helloWorld.sayHello("江霄"); System.out.println("EJB注入成功:"+result); return result; } }
③客户端调用:
public class Client { public static void main(String[] args) throws NamingException { InitialContext initialContext = new InitialContext(); CallHello ejb = (CallHello) initialContext .lookup("CallHelloBean/remote"); String name = ejb.sayHello("周江霄"); System.out.println(name); } }
注意:注释也可以被用在JavaBean风格的setter方法上,效果是相同的。还有一点就是JavaBean的的@Stateful或者@Stateless注释的"mappedName"的属性可以改变JavaBean的JNDI名称,例如@Stateful(mappedName="123"),那么通过JNDI调用就是这样的:
CallHello ejb = (CallHello) initialContext.lookup("123");
2.注入Resource
@EJB注释只能注入EJB存根对象,除@EJB注释之外, EJB 3.0也支持@Resource注释来注入来自JNDI的任何
资源。下面的例子中演示了如何注入数据源。"java:/DefaultMysqLDS"是数据源 DefaultMysqLDS的全局JNDI名。
@Stateless @Remote( { Injection. class }) public class InjectionBean implements Injection { @EJB(beanName = "HelloWorldBean") HelloWorld helloworld; @Resource(mappedName = "java:/DefaultMysqLDS") DataSource myDb; public String SayHello() { String str = ""; try { Connection conn = myDb.getConnection(); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT studentName FROM student"); if (rs.next()) { str = rs.getString(1); } rs.close(); stmt.close(); } catch (sqlException e) { e.printStackTrace(); } return helloworld.SayHello(str); } }