这里有一个小地方值得稍微打断说下,就这个 if (!log.isDebugEnabled())判断。众生周知,若集成第三方日志插件如logback之类,若其配置里去除debug的打印,即时代码里 存在log.debug("xxxxx")也不会打印到控制台,那么,这里增加一个判断 if (!log.isDebugEnabled())是否多次一举呢?
事实上,这里并非多此一举,增加这个判断,是可以提升代码执行效率的。因为log.debug("xxxxx")里的字符串拼接早于log.debug("xxxxx")方法执行的,也就是说,即使该log.debug("xxxxx")不会打印,但其内部的字符串仍然会进行拼接,而拼接,是需要时间的,虽然很细微,但同样属于影响性能范畴内的。因此,增加一个if判断,若无需要打印debug日志时,那么就无需让其内部的字符串进行自动拼接。
这是一个很小的知识点,但面试过程中其实是有可能会遇到这类与日志相关的面试题的。
接下来,让我们继续回到拦截器链的传递上来。
LogInterceptor拦截器调用this.next.execute(config, command),意味着将请求传递到下一个拦截器上进行处理,根据前边分析,可知下一个拦截器是CommandContextInterceptor,根据代码大概可知,这个拦截器内主要是获取上下文配置对象和信息相关的,这些都是在工作流引擎初始化时生成的,它们被保存在Stack栈里,具体都保存了哪些信息暂不展开分析——
public class CommandContextInterceptor extends AbstractCommandInterceptor { ...... public <T> T execute(CommandConfig config, Command<T> command) { CommandContext context = Context.getCommandContext(); boolean contextReused = false; if (config.isContextReusePossible() && context != null && context.getException() == null) { contextReused = true; context.setReused(true); } else { context = this.commandContextFactory.createCommandContext(command); } try { Context.setCommandContext(context); Context.setProcessEngineConfiguration(this.processEngineConfiguration); if (this.processEngineConfiguration.getActiviti5CompatibilityHandler() != null) { Context.setActiviti5CompatibilityHandler(this.processEngineConfiguration.getActiviti5CompatibilityHandler()); } //继续将命令请求传递到下一个拦截器 Object var5 = this.next.execute(config, command); return var5; } catch (Exception var31) { context.exception(var31); } finally { ...... } return null; } }CommandContextInterceptor拦截器没有对命令请求做处理,它继续将请求传递到下一个拦截器TransactionContextInterceptor,根据名字就大概可以猜到,这个拦截器主要是增加与事务有关的功能——
public <T> T execute(CommandConfig config, Command<T> command) { CommandContext commandContext = Context.getCommandContext(); boolean isReused = commandContext.isReused(); Object var9; try { if (this.transactionContextFactory != null && !isReused) { TransactionContext transactionContext = this.transactionContextFactory.openTransactionContext(commandContext); Context.setTransactionContext(transactionContext); commandContext.addCloseListener(new TransactionCommandContextCloseListener(transactionContext)); } var9 = this.next.execute(config, command); } finally { ...... } return var9; }TransactionContextInterceptor拦截器同样没有对命令请求做处理,而是继续传递到下一个拦截器,也就是最后一个拦截器CommandInvoker,根据名字可以大概得知,这是一个与命令请求有关的拦截器,传递过来的请求将会在这个拦截器里处理——
public class CommandInvoker extends AbstractCommandInterceptor { ...... public <T> T execute(CommandConfig config, final Command<T> command) { final CommandContext commandContext = Context.getCommandContext(); commandContext.getAgenda().planOperation(new Runnable() { public void run() { commandContext.setResult(command.execute(commandContext)); } }); this.executeOperations(commandContext); if (commandContext.hasInvolvedExecutions()) { Context.getAgenda().planExecuteInactiveBehaviorsOperation(); this.executeOperations(commandContext); } return commandContext.getResult(); } }