浏览 2356 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2008-02-18
上面的我们看到stripes通过配置文件把框架的大部分功能组件组合在一起,组合在一起,那么怎么有序运行呢?同时不能失去框架的扩展性,不能就顺序执行组件吧,现在的流行的框架都是采用IOC容器来组合这些组件,像structs2采用xwork IOC容器,tapestry5现在采用spring IOC容器。IOC(控制反转)实际上就是拦截器。在servlet Filter中,我们应该知道什么是拦截器吧。Stripes是框架,不能没有扩展性,但stripes又不想弄得太复杂。没有像别的框架借助于别的IOC容器。Stripes实现了一个小的拦截器子系统,6个LifecycleStage在拦截器子系统中执行,同时,stripes又给用户实现拦截器的接口,通过配置,可以在自己的系统中实现功能强大的拦截功能。
Interceptor.java public interface Interceptor { Resolution intercept(ExecutionContext context) throws Exception;} 上面的Interceptor接口的代码,我们可以看出它使用了ExecutionContext,什么是ExecutionContext就是整个stripes执行时上下文,也就是说在stripes框架在执行时,只要调用这个上下文,就可以得整个生命周斯所需要的东西。 ExecutionContext.java public class ExecutionContext { private static final Log log = Log.getInstance(ExecutionContext.class); private Collection<Interceptor> interceptors; private Iterator<Interceptor> iterator; private Interceptor target; private ActionBeanContext actionBeanContext; private ActionBean actionBean; private Method handler; private Resolution resolution; private LifecycleStage lifecycleStage; 。。。。。 public Resolution wrap(Interceptor target) throws Exception { this.target = target; this.iterator = null; return proceed(); } public Resolution proceed() throws Exception { if (this.iterator == null) { log.debug("Transitioning to lifecycle stage ", lifecycleStage); this.iterator = this.interceptors.iterator(); } if (this.iterator.hasNext()) { return this.iterator.next().intercept(this); } else { return this.target.intercept(this); } } } 省去了set,get方法,ExecutionContext就只有两个功能方法。proceed()方法就像servlet filter中proceed()filterChain.doFilter(request, response);运行接下来的过滤器一样,运行下一个拦截器。,ExecutionContext有8个属性。Interceptors是指本生命周期阶段的所有要执行的Interceptor,iterator是指Interceptors集合中某一个,因为采用iterator,所以Interceptor集合中的Interceptor执行是不保证顺序的。也就是说同一个阶段的拦截器不能形成依赖关系。Target是目标Interceptor,每一个阶段都一定执行的Interceptor。Resolution是解析器,就像structs中ActionForward一样。lifecycleStage就是前面讲的6个生命阶段。 我们可以找一个例子: DispatcherHelper.java public static Resolution resolveHandler (final ExecutionContext ctx) throws Exception { final Configuration config = StripesFilter.getConfiguration(); ctx.setLifecycleStage(LifecycleStage.HandlerResolution); ctx.setInterceptors(config.getInterceptors(LifecycleStage.HandlerResolution)); return ctx.wrap( new Interceptor() { public Resolution intercept(ExecutionContext ctx) throws Exception { ActionBean bean = ctx.getActionBean(); ActionBeanContext context = ctx.getActionBeanContext(); ActionResolver resolver = config.getActionResolver(); // Then lookup the event name and handler method etc. String eventName = resolver.getEventName(bean.getClass(), context); context.setEventName(eventName); final Method handler; if (eventName != null) { handler = resolver.getHandler(bean.getClass(), eventName); } else { handler = resolver.getDefaultHandler(bean.getClass()); if (handler != null) { context.setEventName(resolver.getHandledEvent(handler)); } } // Insist that we have a handler if (handler == null) { throw new StripesServletException( "No handler method found for request with ActionBean [" + bean.getClass().getName() + "] and eventName [ " + eventName + "]"); } log.debug("Resolved event: ", context.getEventName(), "; will invoke: ", bean.getClass().getSimpleName(), ".", handler.getName(), "()"); ctx.setHandler(handler); return null; } }); }
这个方面是在生命周期的第二个阶段执行。首先给ExecutionContext设定了所处的阶段,接着去找这个阶段的Interceptors.怎么找呢?它调用了DefaultConfiguration.java中 public Collection<Interceptor> getInterceptors(LifecycleStage stage) { Collection<Interceptor> interceptors = this.interceptors.get(stage); if (interceptors == null) { interceptors = Collections.emptyList(); } return interceptors; } 方法。在这个方法从本实现的所有interceptors取到属性本阶段的。Interceptors是在DefaultConfiguration的init()方法中: this.interceptors = initInterceptors(); if (this.interceptors == null) { this.interceptors = new HashMap<LifecycleStage, Collection<Interceptor>>(); Class<? extends Interceptor> bam = BeforeAfterMethodInterceptor.class; BeforeAfterMethodInterceptor interceptor = new BeforeAfterMethodInterceptor(); for (LifecycleStage stage : bam.getAnnotation(Intercepts.class).value()) { Collection<Interceptor> instances = new ArrayList<Interceptor>(); instances.add(interceptor); this.interceptors.put(stage, instances); } 还记得前面讲过DefaultConfiguration是模版类吗?initInterceptors()在本类是默认的return null实现,推迟到子类实现。看看RuntimeConfiguration.java中@Override protected Map<LifecycleStage, Collection<Interceptor>> initInterceptors() { String classList = getBootstrapPropertyResolver().getProperty(INTERCEPTOR_LIST); if (classList == null) { return null; } else { String[] classNames = StringUtil.standardSplit(classList); Map<LifecycleStage, Collection<Interceptor>> map = new HashMap<LifecycleStage, Collection<Interceptor>>(); for (String className : classNames) { try { Class<? extends Interceptor> type = ReflectUtil.findClass(className.trim()); Intercepts intercepts = type.getAnnotation(Intercepts.class); if (intercepts == null) { log.error("An interceptor of type ", type.getName(), " was configured ", "but was not marked with an @Intercepts annotation. As a ", "result it is not possible to determine at which ", "lifecycle stages the interceprot should be applied. This ", "interceptor will be ignored."); } else { log.debug("Configuring interceptor '", type.getSimpleName(), "', for lifecycle stages: ", intercepts.value()); } // Instantiate it and optionally call init() if the interceptor // implements ConfigurableComponent Interceptor interceptor = type.newInstance(); if (interceptor instanceof ConfigurableComponent) { ((ConfigurableComponent) interceptor).init(this); } for (LifecycleStage stage : intercepts.value()) { Collection<Interceptor> stack = map.get(stage); if (stack == null) { stack = new LinkedList<Interceptor>(); map.put(stage, stack); } stack.add(interceptor); } } catch (Exception e) { throw new StripesRuntimeException( "Could not instantiate one or more configured Interceptors. The " + "property '" + INTERCEPTOR_LIST + "' contained [" + classList + "]. This value must contain fully qualified class names separated " + "by commas.", e); } } return map; } }
这个方法取到配置中的拦截器s,并实例化它们,之后按生命周期分成6类放在renturn中的Map<LifecycleStage, Collection<Interceptor>>中。现在回到resolveHandler方法,这个方法接下来就是return ctx.wrap( new Interceptor() {..});这个实现了一个匿名的Interceptor,之后执行ExcuteContext.wrap(Interceptor)方法。还记得wrap(interceptor),它是一个包扎方法,把这个匿名Interceptor保存ExcuteContext 的target对象。this.target = target;接下的这句 this.iterator = null;仅仅是代码的实现技巧,这个是要在下面的 return proceed();做判断处理。 public Resolution proceed() throws Exception { if (this.iterator == null) { log.debug("Transitioning to lifecycle stage ", lifecycleStage); this.iterator = this.interceptors.iterator(); } if (this.iterator.hasNext()) { return this.iterator.next().intercept(this); } else { return this.target.intercept(this); } } this.iterator = null的作用仅仅是为了找到这一阶段的interceptors。如果找到了就是执行这一阶段的interceptors中的iterator。在这里看到,每一个阶段只能执行一个interceptors的第一个。那剩下的呢怎么办?剩下就是用户实现的拦截器的传递了。如果用户的实现的拦截器没用传递。那之后就不执行,连本阶段的匿名Interceptor都不会执行就直接返回。返回的是Resolution不为null,那个整个流程就结束,剩下的执行Resolution的跳起页面功能(像structs的 ActionForward,比它的功能强)。用户实现的拦截如下: @Intercepts({LifecycleStage.ActionBeanResolution}) public class HibernateInterceptor implements Interceptor { private static Log log = Log.getInstance(HibernateInterceptor.class);private boolean initializedHibernateProvider = false; public Resolution intercept(ExecutionContext context) throws Exception {log.debug("HibernateInterceptor called"); if (!initializedHibernateProvider && (HibernateProvider.getInstance() == null) && (HibernateFilter.getCurrentInstance() != null)) {log.info("Initializing HibernateProvider"); HibernateProvider.setInstance(HibernateFilter.getCurrentInstance()); initializedHibernateProvider = true; } return context.proceed(); } 看到最后一句的:return context.proceed();从现在开始iterator都不为空。那么就找下一个Interceptor,没有的话,就执行本阶段的目标this.target.intercept(this);这个是在本阶段最后执行的。 如果用户采用如下的话: @Intercepts({LifecycleStage.HandlerResolution}) public class NoisyInterceptor implements Interceptor { public Resolution intercept(ExecutionContext ctx) throws Exception { System.out.println("Before " + ctx.getLifecycleStage()); Resolution resolution = ctx.proceed(); System.out.println("After " + ctx.getLifecycleStage()); return resolution}} 那就是一个嵌套的执行,最后还会返回来执行Resolution resolution = ctx.proceed();下面的语句。ctx.proceed()上面的语句是在目标Interceptor之前执行。下面的语句是在目标Interceptor之后执行。Stripes有一个默认的@before和@after就是一个在前面一个后面的实现。分析完了,是不是自己也想写一个interceptor。写interceptor很简单,只要实现implements Interceptor,也就是实现了public Resolution intercept(ExecutionContext ctx) throws Exception就可以。还有一点不能忘记,这个interceptor是在那个阶段执行的,如@Intercepts({LifecycleStage.HandlerResolution})就是在HandlerResolution执行。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |