一、再谈Spring依赖注入:
依赖注入大家应该都不陌生,在Spring 博客系类中队依赖注入以及Spring容器管理依赖都了一定的介绍,简单来说,A调用B,B调用C,Spring框架把这种组件之间的调用关系叫做依赖,也就是说A依赖于B,B依赖于C;通常开发中依赖关系都用New来解决,A依赖于B,那就再A组件中new一个B对象;
这样的弊端就在于A组件调用B的方法,其实并愿理会B的创建问题,直接在A中new B,必然导致硬编码高耦合度,低灵活度的问题。
Spring框架便提出依赖注入的概念,当A依赖于B时,开发者通过配置文件或者注解的方式,由容器负责实例化B,并将B组件实例化对象注入A中,这既是依赖注入。
Spring依赖注入的好处就在于,不仅将依赖关系托于Spring容器进行管理,同时还将组件B已实例化的对象主动注入到A中供A调用,AB之间由容器进行交互,不再直接由A new B组件。
二、EJB依赖注入
EJB最初解决组件间依赖调用是通过JNDI,路径到对象的方式,查找依赖对象。在J2EE5开始也引入了依赖注入的支持。J2EE5的依赖注入分为两种:
1、资源依赖注入
例如组件A依赖于某个数据库资源或者消息数据,这就是资源依赖,用@Resource或@Resources注解表示。
2、EJB依赖注入
EJB依赖主要是组件与组件之间,例如A组件依赖于EJB B组件,用@EJB或@EJBs
表示。@EJB可修饰Bean实现类的成员变量,也可修饰setter方法。
@EJB注解可指定如下属性:
beanInterface:指定被注入的EJB实现类所对应的接口,通常用于区分是远程Bean还是本地Bean。
beanName:指定被注入EJB的名称,与@stateless(name)所指定的值相等。
mappedName:制定被注入EJB的JNDI名。
3、EJB依赖注入实例演示
@Remote
public interface Hello()
{
public String Hello(String name);
}
@Stateless(name="Hello")
public class HelloBean implements Hello
{
..........
}
再添加一个CallHello接口和实现,用于调用Hello
@Remote //接口
public interface CallHello()
{
public String callHello(String name);
}
//实现
@Stateless(mappedName="CallHello")
public class CallHelloBean implements CallHello
{
@EJB(beanName="Hello")
private Hello hello;
public String callHello(String name)
{
//调用注入的hello接口的Hello方法
String result=hello.Hello(name);
System.out.print(result);
}
}
在成员变量hello通过@EJB(beanName="Hello")的修饰,EJB容器就会将该程序中名为“Hello“ 的EJB注入到hello实例变量中。最终实现的结果就是在callHelloBean 中注入了HelloBean 实现类,调用HelloBean .Hello(name)方法。
4、EJB注入的项目应用
在ITOO项目中EJB注入比较通用,主要是通过修饰private 成员变量完成注入。例如,在StudentBeanImpl实现类中依赖StudentEao接口,这是典型的service调用Dao接口的分层逻辑。下面是代码实现:
Eao实现:
@Stateless(name = "studentEaoImpl")
@Remote(StudentEao.class)
@TransactionManagement(TransactionManagementType.CONTAINER)
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class StudentEaoImpl extends BaseEaoImpl<Student> implements StudentEao {
public List queryByList(List list, String dataBaseName) {
........
}
}
在StudentBeanImpl 业务层注入Eao实现,调用queryByList方法
@Stateless(name = "studentBeanImpl")
@Remote(StudentBean.class)
@TransactionManagement(TransactionManagementType.CONTAINER)
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class StudentBeanImpl extends BaseBeanImpl<Student> implements
StudentBean {
/**
* 依赖注入name为"studentEaoImpl"的EJB组件
*/
@EJB(beanName = "studentEaoImpl")
private StudentEao studentEao;
/**
* 根据List<String> ids批量查询,返回List<Map>
*/
@Override
public List<Map<Serializable, Serializable>> queryListByStudentIds(
List<String> ids, String dataBaseName) {
EntityToMap entityToMap = new EntityToMap();
List<Map<Serializable, Serializable>> listStudentInfo = new ArrayList<Map<Serializable, Serializable>>();
List<Student> listStudent = new ArrayList<Student>();
// 调用stuentEao方法
listStudent = studentEao.queryByList(ids, dataBaseName);
listStudentInfo = entityToMap.entityToMap(listStudent);
return listStudentInfo;
}
需要注意的是:从3和4中可以看出,EJB注入的beanName均是Bean实现的stateless(name)值,而stateless在配置name属性时,也是在bean的实现中,所以EJB注入应该是针对bean实现与实现之间,跟接口其实没联系。所以方便使用,开发者只需要知道在实现中配置session Bean状态@stateless(name=
””
),同样,也在实现Bean中注入EJB(beanName=”实现类stateless_name“)即可。