双向注入
Dependency injection(依赖注入) 和 inversion of control(控制反转) 现在对大多数Java 开发者来说都是熟悉的概念了。依赖注入允许一个组件通过容器“注入”另一个组件到一个setter方法或者实例变量的方式,来获得被“注入”组件的引用 (reference)。我们之前看过的所有依赖注入的实现,注入发生在组件创建的时候,在此后实例的整个生命周期中不再改变。对无状态组件,这么做是有道理的。从客户端的角度来看,特定种类的无状态组件的所有实例都是可以替换的。另一方面,Seam着重处理有状态组件。此时传统的依赖注入不再是非常有效了。Seam引入了 bijection(双向注入) 这个名词,用来作为注入的广义概括。和injection(单向注入)对比,bijection是:
*
contextual(上下文相关的) - 双向注入用来针对不同的上下文来组装有状态组件(在较大范围的上下文中的组件,可以引用较小范围上下文中的组件)
*
bidirectional(双向的) - 被触发后,值从上下文变量中注射到组件属性中,也可以从组件属性outjected(反向注入) 回上下文,这样被调用的组件可以只通过改写自己的实例变量就同时操作了上下文变量的值
*
dynamic(动态的) - 因为上下文变量的值随着时间不断改变,而且因为Seam组件是有状态的,双向注入在每次组件被调用的时候都发生。
基本上,通过设置实例变量是需要注入、反向注入、还是二者皆是,双向注入让你将上下文变量映射到组件实例变量。当然,我们使用注解来设置双向注入。
@In 注解指明应该注入值,可能是注入实例变量:
@Name("loginAction")
@Stateless
public class LoginAction implements Login {
@In User user;
...
}
或者注入setter方法:
@Name("loginAction")
@Stateless
public class LoginAction implements Login {
User user;
@In
public void setUser(User user) {
this.user=user;
}
...
}
默认情况下,针对被注入的属性或者实例变量名, Seam会对所有的上下文进行优先级搜索。 如果你希望明确指定上下文变量名,可以这样写:@In("currentUser")。
如果没有组件实例绑定到具名的上下文变量,你可能希望Seam创建一个,你可以指定 @In(create=true)。 如果值是可选的(可以为null),请指定 @In(required=false)。
对于某些组件,到处指定 @In(create=true) 是很繁琐的。 你可以注解整个组件为 @AutoCreate,它就会在任何需要的时候自动创建,不需要明确的指定 create=true。
你还可以注入表达式的值:
@Name("loginAction")
@Stateless
public class LoginAction implements Login {
@In("#{user.username}") String username;
...
}
(在下一章,有更多的关于组件生命周期和注射的内容。)
@Out 注解指定了某个属性需要对外注入,可能是从实例变量:
@Name("loginAction")
@Stateless
public class LoginAction implements Login {
@Out User user;
...
}
或者从某个getter方法:
@Name("loginAction")
@Stateless
@Interceptors(SeamInterceptor.class)
public class LoginAction implements Login {
User user;
@Out
public User getUser() {
return user;
}
...
}
属性可以既是被注入的,也可以对外注入:
@Name("loginAction")
@Stateless
public class LoginAction implements Login {
@In @Out User user;
...
}
或者:
@Name("loginAction")
@Stateless
public class LoginAction implements Login {
User user;
@In
public void setUser(User user) {
this.user=user;
}
@Out
public User getUser() {
return user;
}
...
}
---------------------------------------------------------------------------------------------------------------------------
Factory和Manager组件
我们经常需要与非Seam组件的对象打交道。但是我们仍然希望把它们通过 @In 注入我们的组件,并在值和方法表达式中使用它们。 有时候,我们甚至需要把它们绑定到Seam 上下文的生命周期里(例如@Destroy)。 所以Seam上下文可以容纳非Seam组件的对象,并且Seam提供了一些很好的特性,这些特性使得我们与绑定到上下文里的非组件对象打交道更加容易。
factory component pattern(工厂组件模式)让Seam组件作为非组件对象的构造器。 当上下文变量被引用,但是没有值被绑定到它时,会调用一个factory method(工厂方法)。 我们通过@Factory注解来定义工厂方法。 工厂方法把一个值绑定到上述上下文变量,并且决定被绑定的值的范围。有两种工厂方法。第一种返回一个值,Seam会把它绑定到上下文里:
@Factory(scope=CONVERSATION)
public List<Customer> getCustomerList() {
return ... ;
}
第二种方法返回 void,它自己把值绑定到上下文变量:
@DataModel List<Customer> customerList;
@Factory("customerList")
public void initCustomerList() {
customerList = ... ;
}
两种情况下,当我们引用 customerList 上下文变量,而其值为null时,工厂方法被调用,然后对这个值生命周期的其他部分就无法操纵了。 更加强大的模式是 manager component pattern(管理者组件模式)。 在这种情况下,有一个Seam组件绑定到上下文变量,它管理着上下文变量的值,对客户端不可见。
管理者组件可以是任何组件,它需要一个 @Unwrap 方法。 该方法返回对客户端可见的值,每次 上下文变量被引用的时候都会被调用。
@Name("customerList")
@Scope(CONVERSATION)
public class CustomerListManager
{
...
@Unwrap
public List<Customer> getCustomerList() {
return ... ;
}
}
当你有一个对象并需要对其组件的生命周期更多的控制时,管理组件模式就显得尤其有用。 例如,如果你有一个重量级的对象,当上下文结束时你想对其进行清除操作,你可以@Unwrap对象,并在管理组件的 @Destroy 方法中执行清除操作。
@Name("hens")
@Scope(APPLICATION)
public class HenHouse {
Set<Hen> hens;
@In(required=false) Hen hen;
@Unwrap
public List<Hen> getHens() {
if (hens == null) {
// Setup our hens
}
return hens;
}
@Observer({"chickBorn", "chickenBoughtAtMarket"})
public addHen() {
hens.add(hen);
}
@Observer("chickenSoldAtMarket")
public removeHen() {
hens.remove(hen);
}
@Observer("foxGetsIn")
public removeAllHens() {
hens.clear();
}
...
}
这里,被管理的组件观察那些改变在下面的对象的事件。组件自己管理这些动作,并且由于对象在每一次访问中都被解开,所以这里提供了一个统一的视图。
分享到:
相关推荐
Seam - 语境相关的组件[满江红20071230]............................................................................................................................ 1 Java EE 框架...........................
Seam - 语境相关的组件 ,学习seam的好资料.
Algorithm-seam-carving-js.zip,seam-carver的javascript实现。seam carver是一种基于内容的图像缩放算法,算法是为计算机程序高效、彻底地完成任务而创建的一组详细的准则。
对于一个图片seam carving的横向和纵向删除seam的操作,可以显示出seam曲线(matlab)
JBoss_Seam--中文、Seam教程,中文Seam针对初学者很好的讲解及实例。希望对您有所收获。
2007年Shai Avidan 和Ariel Shamir论文《Seam Carving for Content-Aware Image Resizing》所提出方法的Matlab代码实现和作者的论文。 效果非常炫,而且代码不长
JBoss Seam In Action
运用seamcarving的方式,实现了对主体感知的图像放缩,以及删除图片中选中的部分
seam carving定义了穿过整幅图像的像素线(即seam),它是由图像中最低能量的像素组成的。如左下图中画出了一个横向的seam和一个纵向的seam。
java jboss seam jboss-seam-selectitems
seam setup 输入项目原型和数据库信息 seam create-project 创建基础项目结构 seam generate 反向工程数据库,创建管理数据库的CRUD程
Seam framework power point material.
JBOSS SEAM组件中文手册 Seam_2.0_Reference_zh_CN
Seam-Carving-Kotlin
seam-978-1-8471-9592-0 Seam 2.x 网页开发
本文介绍了JBoss Seam的产生背景以及集成框架的概念,并且演示了在JBoss Seam中如何使用POJOs处理JSF事件以及实现双向依赖注入。
对JBoss Seam及其上下文相关的组件模型等的介绍 资源中包括两个文档,但是内容一样,怎么方便怎么看
为一个类定义一个Seam组件。所有Seam组件都需要该注解。 @Scope @Scope(ScopeType.CONVERSATION) 定义默认的组件上下文。可以定义的值由 ScopeType 枚举:EVENT, PAGE, CONVERSATION, SESSION, BUSINESS_PROCESS, ...
接缝雕刻使用 OpenCV 中描述的算法在 C++ 中的实现用于内容感知图像大小调整的 Seam Carving ( ) 用于视频重定向的改进接缝雕刻 ( )