一、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属性,默认为不带包名的类名)
不同服务器存在不同的差异.
举例:通过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);
}
}
总结:刚开始学习EJB注入的是时候,被几个name、mappedName、beanName搞混了,然后就自己动手敲了个Demo,在实践中验证自己的想法,这样往往比只停留在理论上要理解的深刻。