jboss seam 中的Interceptor

在Seam Framework中,Interceptor完成简单的AOP功能,本文分析Interceptor的处理流程。

在创建Seam组件的Component类时,有一段初始化Interceptor的代码:

if ( interceptionEnabled ) {
initInterceptors();
}

不过可以通过在Seam组件上使用@BypassInterceptors注解以禁止使用Interceptor.

Component.initInterceptors()

initDefaultInterceptors(); // 初始化默认的Interceptor

// 加入用户的Interceptor.
for (Annotation ann : getBeanClass().getAnnotations() ) {
if (annotation.annotationType().isAnnotationPresent(Interceptors.class)) {
Class[] classes = annotation.annotationType().getAnnotation(Interceptors.class).value;
addInterceptor(new Interceptor(classes, annotation, this));
}
}

这里的Interceptors注解类可以是org.jboss.seam.annotations.intercept.Interceptors
也可以是 javax.interceptor.Interceptors,
要注意的是,Interceptors注解不能直接加到Bean中,而应该通过一个注解间接地加到Bean上,
通过上面的代码可以看出这一点。

Component.initDefaultInterceptors()

//根据组件类型初始化Interceptors,这里只给出其中的两个:
if (getType()!=ENTITY_BEAN) {
addInterceptor(new Interceptor(new MethodContextInterceptor(), this));
}
if (needsInjection() || needsOutjection()) { // 需要注入或反向注入
addInterceptor(new Interceptor(new BijectionInterceptor(), this));
}

BijectionInterceptor即双向注入拦截器,稍后我们来看它是如何工作的。

在Seam Framework中,并不要求Interceptor继承自某个Interface或Class,
只要在Invoke方法上加@AroundInvoke注解即可,这样任何一个Pojo类都可以成为Interceptor,
当然,如果让Interceptor继承自Seam中的AbstractInterceptor,那么能得到一些性能上的优化,
稍后我们会看到这一点。

下面以普通JavaBean为例来说明Interceptor的处理流程

Component.initantiateJavaBean()

Object bean = getBeanClass().newInstance();
JavaBeanInterceptor interceptor = new JavaBeanInterceptor(bean, this);
bean = wrap(bean, interceptor);
interceptor.postConstruct();
return bean;


在bean创建后,为其创建一个JavaBeanInterceptor,然后创建一个proxy对象返回,
这样对bean的所有调用都将由JavaBeanInterceptor进行处理。

JavaBeanInterceptor.invoke(proxy, method, proceed, params)

Object result = interceptInvocation(method, params);
return result==bean ? proxy : result;


JavaBeanInterceptor.interceptInvocation(method, params)

return invoke(new RootInvocationContext(bean, method, params), EventType.AROUND_INVOKE);


RootInterceptor.invoke(invocation, invocationType)
  
if (!isSeamComponent || !Lifecycle.isApplicationInitialized()) {
// 不是一个seam组件,直接调用方法
return invocation.proceed();
}
else {
return createInvocationContext(invocation, invocationType).proceed();
}


RootInterceptor.createInvocationContext(invocation, invocationType)

if (isProcessInterceptors(invocation.getMethod(), invocation.getTarget())) {
// 检查method是否要处理拦截,在Method上也可以加BypassInterceptors注解来忽略拦截器
return createSeamInvocationContext(invocation, invocationType);
}
else {
return invocation;
}


SeamInvocationContext.proceed()

if (location == interceptors.size) {
// 所有Interceptor是否已处理完
return context.proceed();
}
else {
Object userInterceptor = userInterceptors.get(location);
Interceptor interceptor = interceptors.get(location);
location++;
switch (eventType) {
case AROUND_INVOKE:
if (interceptor.isOptimized()) {
// 检查Interceptor是否继承自OptimizedInterceptor
return ((OptimizedInterceptor)userInterceptor).aroundInvoke(this);
}
else {
return interceptor.aroundInvoke(this, userInterceptor);
}
case .....
}
}

这是一个Interceptor链的处理方法,每进入一个Interceptor,location加一,
直到所有Interceptor都进入才执行实际的业务方法,然后按相反顺序退出Interceptor链,
所以在业务方法中必须调用invocation.proceed()以使Interceptor链进行下去。

Interceptor.aroundInvoke(invocation, userInterceptor)

return aroundInvokeMethod==null ?
invocation.proceed() :
Reflections.invoke( aroundInvokeMethod, userInterceptor, invocation );

如果aroundInvokeMethod为null,则继续下一Interceptor,
否则执行userInterceptor的aroundInvokeMethod。


双向注入

双向注入由BijectionInterceptor拦截器完成,双向注入只是IoC的一个扩展,其中
正向注入把Context中的对象到Seam组件中,反向注入把Seam组件的对象注入到Context中,

BijectionInterceptor.aroundInvoke(invocation)

Component component = getComponent();
boolean enforceRequired = !component.isLifecycleMethod(invocation.getMethod());
// 正向注入
component.inject(invocation.getTarget(), enforceRequired);
// 业务方法
Object result = invocation.proceed();
// 反向注入
component.outject(invocation.getTarget(), enforeRequried);
component.disinject(invocation.getTarget());
return result;

有关双向注入的详细内容请查看后续文章。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值