WireBox : Dependency Injection & AOP
5.x
5.x
  • Introduction
  • Intro
    • Introduction
      • What's New With 5.5.0
      • What's New With 5.4.0
      • What's New With 5.3.0
      • What's New With 5.0.0
      • What's New With 2.1.0
      • What's New With 2.0.0
      • About This Book
      • Author
  • Getting Started
    • Overview
    • Installing WireBox
    • Getting Jiggy Wit It!
      • Instance Creations
      • Binder Introduction
      • Scoping
      • Eager Init
      • How WireBox Resolves Dependencies
  • Configuration
    • Configuring WireBox
      • Binder Configuration Properties
      • Binder Environment Properties
      • ColdBox Enhanced Binder
      • Types & Scopes
      • Data Configuration Settings
      • Programmatic Configuration
    • Mapping DSL
      • Mapping Initiators
      • Mapping Destinations
      • MapDirectory() Influence & Filters
      • Persistence DSL
      • Dependencies DSL
        • Mapping Extra Attributes
      • Mapping DSL Examples
      • Influence Instances at Runtime
      • Processing Mappings
    • Component Annotations
      • Persistence Annotations
      • CacheBox Annotations
    • Parent Object Definitions
  • Usage
    • WireBox Injector
      • Injector Constructor Arguments
      • Injection Idioms
      • Common Methods
    • Injection DSL
      • ID-Model-Empty Namespace
      • Provider Namespace
      • WireBox Namespace
      • CacheBox Namespace
      • EntityService Namespace
      • LogBox Namespace
      • Java Namespace
      • ColdBox Namespace
    • WireBox Event Model
      • WireBox Events
      • WireBox Listeners
        • ColdBox Mode Listener
        • Standalone Mode Listener
  • Advanced Topics
    • Providers
      • Custom Providers
      • toProvider() closures
      • Virtual Provider Injection DSL
      • Virtual Provider Mapping
      • Virtual Provider Lookup Methods
      • Provider onMissingMethod Proxy
      • Scope Widening Injection
    • Virtual Inheritance
    • Runtime Mixins()
    • Object Persistence & Thread Safety
    • ORM Entity Injection
    • WireBox Object Populator
      • populateFromXML
      • populateFromQuery
      • populateFromStruct
      • populateFromQueryWithPrefix
      • populateFromJSON
  • Extending WireBox
    • Custom DSL
      • The DSL Builder Interface
      • Registering a Custom DSL
    • Custom Scopes
      • The Scope Interface
      • Scoping Process
      • Registering a Custom Scope
    • WireBox Injector Interface
  • Aspect Oriented Programming
    • AOP Intro
      • Overview
        • AOP Vocabulary
      • Activate The AOP Listener
      • Create Your Aspect
        • MethodInvocation Useful Methods
        • MethodLogger Aspect
      • Aspect Registration
      • Aspect Binding
      • Auto Aspect Binding
        • ClassMatcher Annotation DSL
        • MethodMatcher Annotation DSL
      • Included Aspects
        • CFTransaction
        • HibernateTransaction
        • MethodLogger
      • Summary
Powered by GitBook
On this page

Was this helpful?

Edit on Git
Export as PDF
  1. Aspect Oriented Programming
  2. AOP Intro
  3. Create Your Aspect

MethodLogger Aspect

Here is my MethodLogger aspect that I will create:

<cfcomponent output="false" implements="wirebox.system.aop.MethodInterceptor" hint="A simple interceptor that logs method calls and their results">

    <---  Dependencies --->
    <cfproperty name="log" inject="logbox:logger:{this}">

    <---  init --->
    <cffunction name="init" output="false" access="public" returntype="any" hint="Constructor">
        <cfargument name="logResults" type="boolean" required="false" default="true" hint="Do we log results or not?"/>
        <cfscript>
            instance = {
                logResults = arguments.logResults
            };

            return this;
        </cfscript>
    </cffunction>

    <---  invokeMethod --->
    <cffunction name="invokeMethod" output="false" access="public" returntype="any" hint="Invoke an AOP method invocation">
        <cfargument name="invocation" required="true" hint="The method invocation object: wirebox.system.aop.MethodInvocation">
        <cfscript>
            var refLocal = {};
            var debugString = "target: #arguments.invocation.getTargetName()#,method: #arguments.invocation.getMethod()#,arguments:#serializeJSON(arguments.invocation.getArgs())#";

            // log incoming call
            log.debug(debugString);

            // proceed execution
            refLocal.results = arguments.invocation.proceed();

            // result logging and returns
            if( structKeyExists(refLocal,"results") ){
                if( instance.logResults ){
                    log.debug("#debugString#, results:", refLocal.results);
                }
                return refLocal.results;
            }
        </cfscript>
    </cffunction>

</cfcomponent>

You can see that I do some DI via annotations:

<---  Dependencies --->
<cfproperty name="log" inject="logbox:logger:{this}">

A normal constructor with one optional argument for logging results:

<---  init --->
<cffunction name="init" output="false" access="public" returntype="any" hint="Constructor">
    <cfargument name="logResults" type="boolean" required="false" default="true" hint="Do we log results or not?"/>
    <cfscript>
        instance = {
            logResults = arguments.logResults
        };

        return this;
    </cfscript>
</cffunction>

And our invokeMethod implementation:

<---  invokeMethod --->
<cffunction name="invokeMethod" output="false" access="public" returntype="any" hint="Invoke an AOP method invocation">
<cfargument name="invocation" required="true" hint="The method invocation object: wirebox.system.aop.MethodInvocation">
<cfscript>
    var refLocal = {};
    var debugString = "target: #arguments.invocation.getTargetName()#,method: #arguments.invocation.getMethod()#,arguments:#serializeJSON(arguments.invocation.getArgs())#";

    // log incoming call
    log.debug(debugString);

    // proceed execution
    refLocal.results = arguments.invocation.proceed();

    // result logging and returns
    if( structKeyExists(refLocal,"results") ){
        if( instance.logResults ){
            log.debug("#debugString#, results:", refLocal.results);
        }
        return refLocal.results;
    }
</cfscript>
</cffunction>

As you can see, the before advice part is what happens before the execution of the real method (or more aspects) occurrs. So everything before the call to arguments.invocation.proceed():

var refLocal = {};
var debugString = "target: #arguments.invocation.getTargetName()#,method: #arguments.invocation.getMethod()#,arguments:#serializeJSON(arguments.invocation.getArgs())#";

// log incoming call
log.debug(debugString);

Then we execute the real method or more aspects (we do not do anything around the method call):

// proceed execution
refLocal.results = arguments.invocation.proceed();

Finally, we do the after advice part which happens after the method or other aspects fire and results are returned:

// result logging and returns
if( structKeyExists(refLocal,"results") ){
    if( instance.logResults ){
        log.debug("#debugString#, results:", refLocal.results);
    }
    return refLocal.results;
}

That's it. I have succesfully created an aspect. What's next!

PreviousMethodInvocation Useful MethodsNextAspect Registration

Last updated 7 years ago

Was this helpful?