在cubby里可以使用plugin实现拦截器。通常的做法是重载plugin的invokeAction方法对Action方法进行拦截。
执行顺序
CubbyFilter --> Action.initialize() --> Plugin.invokeAction() --> Actoin.xxx()
plugin代码示例
public class TestPlugin extends AbstractPlugin {
@Override
public ActionResult invokeAction(final ActionInvocation invocation)
throws Exception {
//Action前的处理
......
//Action处理xxxAction action = (xxxAction) invocation.getActionContext().getAction();
ActionResult result = super.invokeAction(invocation);
//Action后的处理
......
return result;
}
}
com.example.plugin.TestPlugin
这里的文件名和文件位置是固定的。可以查看Cubby源代码的plugin加载类:
org.seasar.cubby.internal.util.ServiceLoader
这个类里的代码
private static final String PREFIX = "META-INF/services/";
决定了文件的位置。
而通过这个类里的代码
final String resourceName = PREFIX + service.getName();
可以发觉文件名就是从plugin管理类
org.seasar.cubby.internal.plugin.PluginManager
的代码
for (final Plugin plugin : ServiceLoader.load(Plugin.class)) {
plugins.add(plugin);
}
传递过来的Plugin.class的完整类名,即org.seasar.cubby.plugin.Plugin。
所以,这个文件的名字和位置是有框架的源代码决定的固定值。
另外,通过源代码可以发现,在ServiceLoader类中,加载的plugin是存储在LinkedHashMap<String, S>中的,因此这时候是有序的。
而在返回到类PluginManager时,plugin是存储在LinkedHashSet<Plugin>中的,因此,到这里为止plugin还是有序的。
但是,PluginManager里把plugin加载到类PluginRegistry中的时候,是存储在HashSet<Plugin>里的,所以最后又变成无序的了。
而执行plugin的代码是在类ActionProcessorImpl中以下代码取得类PluginRegistry里的plugin的迭代器,
this.pluginsIterator = pluginRegistry.getPlugins().iterator();
也就是说最终执行plugin时是无序的。
所以,如果需要有序的多个拦截器的话,不要用创建多个plugin的方法。
可以在一个plugin里调用多个类来处理;
也可以把一些前面的处理放到Action的initialize()里 。