         Batman.developer.error("Please define `routingKey` on the prototype of #{Batman.functionName(@constructor)} in order for your controller to be minification safe.") if Batman.config.minificationErrors
         Batman.functionName(@constructor).replace(/Controller$/, '')
 
-  _optionsFromFilterArguments = (options, nameOrFunction) ->
-    if not nameOrFunction
-      nameOrFunction = options
-      options = {}
-    else
-      if typeof options is 'string'
-        options = {only: [options]}
-      else
-        options.only = [options.only] if options.only and Batman.typeOf(options.only) isnt 'Array'
-        options.except = [options.except] if options.except and Batman.typeOf(options.except) isnt 'Array'
-    options.block = nameOrFunction
-    options
+  @classMixin Batman.LifecycleEvents
+  @lifecycleEvent 'filter', (options = {}) ->
+    normalized = {}
+    only = if Batman.typeOf(options.only) is 'String' then [options.only] else options.only
+    except = if Batman.typeOf(options.except) is 'String' then [options.except] else options.except
 
-  @beforeFilter: ->
-    Batman.initializeObject this
-    options = _optionsFromFilterArguments(arguments...)
-    filters = @_batman.beforeFilters ||= []
-    filters.push(options)
+    normalized.if = (params) ->
+      return false if @_afterFilterRedirect
+      return false if only and params.action not in only
+      return false if except and params.action in except
+      return true
 
-  @afterFilter: ->
-    Batman.initializeObject this
-    options = _optionsFromFilterArguments(arguments...)
-    filters = @_batman.afterFilters ||= []
-    filters.push(options)
+    return normalized
 
   @afterFilter (params) ->
     if @autoScrollToHash && params['#']?

        @_afterFilterRedirect = url
    else
      if Batman.typeOf(url) is 'Object'
        url.controller = @ if not url.controller

      Batman.redirect url


    @executeAction(action, params)

    redirectTo = @_afterFilterRedirect
    @_afterFilterRedirect = null
    delete @_afterFilterRedirect

    Batman.redirect(redirectTo) if redirectTo

  executeAction: (action, params = @get('params')) ->
    Batman.developer.assert @[action], "Error! Controller action #{@get('routingKey')}.#{action} couldn't be found!"

    parentFrame = @_actionFrames[@_actionFrames.length - 1]
    frame = new Batman.ControllerActionFrame {parentFrame, action}, =>
      @fireLifecycleEvent('afterFilter', params) if not @_afterFilterRedirect
      @_resetActionFrames()
      Batman.navigator?.redirect = oldRedirect

    @_actionFrames.push(frame)
    frame.startOperation(internal: true)

    oldRedirect = Batman.navigator?.redirect
    Batman.navigator?.redirect = @redirect

    @fireLifecycleEvent('beforeFilter', params)
    result = @[action](params) if not @_afterFilterRedirect

    @render() if not frame.operationOccurred
    frame.finishOperation()
