(本文是转载其他人的技术文章,觉得说得挺浅显易懂,特借来学习)
在前面学习的例子中,只有一个EJB,但是对于一个真实的项目,EJB的数量可以有很多,而且EJB之间也会互相调用,那么在一个EJB里面,如何去调用另一个EJB呢?这正是本节要介绍的内容。
新建一个bean
Other.java
public interface Other {
public String sayMe();
}
OtherBean.java
@Stateless
// 不写的话默认是本地接口
public class OtherBean implements Other {
public String sayMe() {
return "other";
}
}
现在是要在HelloWorldBean里面调用OtherBean里面的sayMe方法。 那么我们在helloworld里面怎么获取otherbean ejb呢?有人可能去想到这种方法:
public class HelloWorldBean implements HelloWorld, HelloWorldLocal {
private Other other = new OtherBean();
public String sayHello(String name) {
return name + "说:你好," + other.sayMe();
}
}
这种方法是绝对错误的,如果通过这种方法得到的对象,它不是EJB对象,而只是一个简简 单单的Java对象。
我们要得到一个EJB对象,我们可以采用两种方法。一种方法是通过JNDI查找,第二种方法是采用依赖注入。那么我们首先学一下通过JNDI查找的方式来得到other
EJB。
HelloWorldBean.java
@Stateful //指明这个ejb是无状态的会话bean
@Remote(HelloWorld.class) //将HelloWorld这个接口指定为远程接口
@Local(HelloWorld.class) //将HelloWorld这个接口指定为本地接口
//在这个EJB里面,不单具有本地接口,也有远程接口
public class HelloWorldBean implements HelloWorld, HelloWorldLocal {
public String sayHello(String name) {
try {
InitialContext ctx = new InitialContext();
Other other = (Other)ctx.lookup("OtherBean/local");
return name + "说:你好," + other.sayMe();
} catch (NamingException e) {
e.printStackTrace();
}
return null;
}
}
EJBClient.java
public class EJBClient {
public static void main(String[] args) {
try {
InitialContext ctx = new InitialContext();
HelloWorld helloworld = (HelloWorld) ctx.lookup("HelloWorldBean/remote");
System.out.println(helloworld.sayHello("注入者"));
} catch (NamingException e) {
System.out.println(e.getMessage());
}
}
}
除了JNDI查找的方式外,还可以通过依赖注入的方式来得到other
ejb。
HelloWorldBean.java
@Stateful //指明这个ejb是无状态的会话bean
@Remote(HelloWorld.class) //将HelloWorld这个接口指定为远程接口
@Local(HelloWorld.class) //将HelloWorld这个接口指定为本地接口
//在这个EJB里面,不单具有本地接口,也有远程接口
public class HelloWorldBean implements HelloWorld, HelloWorldLocal {
@EJB Other other; //通过这个注解就可以把EJB注入进来
public String sayHello(String name) {
return name + "说:你好," + other.sayMe();
}
}
大家比较一下,采用EJB注解注入other EJB,和采用JNDI查找的方式来得到EJB,在代码量上面显然@EJB注解代码量更少,而且在使用上面比JNDI的方式更优雅一些。
那么以后大家在做项目的时候,如果要使用到别的EJB的话,可以采用注解的方式来注入要使用的EJB。
@EJB Other other; 这种注入它里面的工作原理是怎样的呢?
大概是这样的:EJB容器当解释到类里面的字段当带有@EJB注解的时候,它就会根据这个字段other的类型也就是接口Other去寻找是否有实现了这个接口的EJB,如果寻找到了实现了Other这个接口的EJB,并且只寻找到一个的时候,那么它就会把这个EJB注入进来。
那么有同学会问:如果寻找到了两个EJB都实现了Other这个接口,那会出现什么问题呢? 这时候会报一个错,因为它不知道我们需要注入哪一个。
那么这时候又可能会有同学会问:是不是没有办法解决这个问题呢? 当然,办法是有的。
当出现这种情况的时候,我们就要明确指定我们需要注入的是哪一个EJB。 现在假设Other这个接口被两个EJB实现了,我们要注入的是OtherBean这个EJB,那么我们会这样:
@EJB(beanName="OtherBean") Other
other; 通过这种形式就可以明确指定需要注入的EJB了,哪怕Other这个接口已被很多EJB实现了。
@EJB这个EJB注解它只能够注入EJB,其它那些资源类型是不能采用这个注解来注入的。那么好比我们现在要使用EJB里面的定时服务,这时候我们就不能使用这个@EJB来注入定时服务了。
那么我们应该使用哪些注解呢?应该使用@Resource注解,好比我们要注入定时服务:@Resource TimerService timerService; 注入数据源,也是用@Resource注解
相关文章
- 可采用两种方法得到一个EJB对象
- Winform主菜单两种实现方式-1.)从工具箱中双击MenuStrip控件,窗体的顶部就会放置一个MenuStrip控件,或者在工具箱中单击MenuStrip控件,拖至窗体中也可以. 2.)在MenuStrip的“Type Here”输入主菜单和菜单名字,热键用(&X)表示. 用快捷键选择主菜单,可以用Alt + 预定义的按键来实现,子菜单的选择只需要按定义的热键即可. 3.)双击File*菜单下面的子菜单,创建子菜单Open、Save、Exit的单击事件代码: private void OpenOToolStripMenuItem_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog { //初始化打开对话框的路径 InitialDirectory = @"D:\", Title = "Open File", //定义可显示的文件类型; Filter = "txt file(*.txt)|*.txt|All file(*.*)|*.*", //定义默认显示的文件类型为txt FilterIndex = 1, //对话框关闭后将复位初始化路径 RestoreDirectory = true }; if (ofd.ShowDialog == DialogResult.OK) { //根据打开对话框选择的文件名,加载文本内容到富文本框中. richtxtContent.Text = File.ReadAllText(ofd.FileName); } } private void SaveSToolStripMenuItem_Click(object sender, EventArgs e) { SaveFileDialog sfd = new SaveFileDialog { //初始化保存对话框的路径 InitialDirectory = @"D:\", Title = "Save File", //定义可显示的文件类型; Filter = "txt file(*.txt)|*.txt|All file(*.*)|*.*", //定义默认显示的文件类型为txt FilterIndex = 1, //对话框关闭后将复位初始化路径 RestoreDirectory = true }; if(sfd.ShowDialog == DialogResult.OK) { //保存文件 File.WriteAllText(sfd.FileName, richtxtContent.Text); //清空富文本框内容 richtxtContent.Clear; } } private void exitEToolStripMenuItem_Click(object sender, EventArgs e) { Application.Exit; } 4.)执行下程序,加载指定的txt文件到富文本框中,如下: 5.)在富文本框中更新加载进来的txt文件内容. 6.)Alt + F热键打开文件的下拉菜单,单击S保存富文本框中的内容到指定的文件.打开txt验证菜单单击事件保存文件成功. 二.实现winform主菜单的方法2:MenuStrip类和toolStripMenuItem类实例化对象,在主窗体加载事件中实现如下代码:
- Java 数据结构-特点: 代表一个队列,通常按照先进先出(FIFO)的顺序操作元素。 实现类: LinkedList, PriorityQueue, ArrayDeque。 堆(Heap) 堆(Heap)优先队列的基础,可以实现最大堆和最小堆。 PriorityQueue<Integer minHeap = new PriorityQueue<>; PriorityQueue<Integer maxHeap = new PriorityQueue<>(Collections.reverseOrder); 树(Trees) Java 提供了 TreeNode 类型,可以用于构建二叉树等数据结构。 class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int x) { val = x; } } 图(Graphs) 图的表示通常需要自定义数据结构或使用图库,Java 没有内建的图类。 以上介绍的只是 Java 中一些常见的数据结构,实际上还有很多其他的数据结构和算法可以根据具体问题选择使用。 其他一些说明 以下这些类是传统遗留的,在 Java2 中引入了一种新的框架-集合框架(Collection),我们后面再讨论。 枚举(Enumeration) 枚举(Enumeration)接口虽然它本身不属于数据结构,但它在其他数据结构的范畴里应用很广。 枚举(The Enumeration)接口定义了一种从数据结构中取回连续元素的方式。 例如,枚举定义了一个叫nextElement 的方法,该方法用来得到一个包含多元素的数据结构的下一个元素。 关于枚举接口的更多信息,请参见枚举(Enumeration)。 位集合(BitSet) 位集合类实现了一组可以单独设置和清除的位或标志。 该类在处理一组布尔值的时候非常有用,你只需要给每个值赋值一"位",然后对位进行适当的设置或清除,就可以对布尔值进行操作了。 关于该类的更多信息,请参见位集合(BitSet)。 向量(Vector) 向量(Vector)类和传统数组非常相似,但是Vector的大小能根据需要动态的变化。 和数组一样,Vector对象的元素也能通过索引访问。 使用Vector类最主要的好处就是在创建对象的时候不必给对象指定大小,它的大小会根据需要动态的变化。 关于该类的更多信息,请参见向量(Vector) 栈(Stack) 栈(Stack)实现了一个后进先出(LIFO)的数据结构。 你可以把栈理解为对象的垂直分布的栈,当你添加一个新元素时,就将新元素放在其他元素的顶部。 当你从栈中取元素的时候,就从栈顶取一个元素。换句话说,最后进栈的元素最先被取出。 关于该类的更多信息,请参见栈(Stack)。 字典(Dictionary) 字典(Dictionary) 类是一个抽象类,它定义了键映射到值的数据结构。 当你想要通过特定的键而不是整数索引来访问数据的时候,这时候应该使用 Dictionary。 由于 Dictionary 类是抽象类,所以它只提供了键映射到值的数据结构,而没有提供特定的实现。 关于该类的更多信息,请参见字典( Dictionary)。 Dictionary 类在较新的 Java 版本中已经被弃用(deprecated),推荐使用 Map 接口及其实现类,如 HashMap、TreeMap 等,来代替 Dictionary。
- MongoDB用Mongoose得到的对象不能增加属性完美解决方法(两种)
- 得到一个String类型的首位两种方法
- Delphi函数指针的两种定义(对象方法存在一个隐藏参数self,所以不能相互赋值)
- Delphi函数指针的两种定义(对象方法存在一个隐藏参数self,所以不能相互赋值)
- 声明一个set集合,使用HashSet类,来保存十个字符串信息,然后通过这个集合,然后使用iterator()方法,得到一个迭代器,遍历所有的集合中所有的字符串;然后拿出所有的字符串拼接到一个StringBuffer对象中,然后输出它的长度和具体内容; 验证集合的remove()、size()、contains()、isEmpty()等