Class: Aquarium::Aspects::Aspect

Inherits:
Object
  • Object
show all
Includes:
Aquarium::Aspects, Advice, DefaultObjectsHandler, ExclusionHandler, Utils::ArrayUtils, Utils::HashUtils, Utils::HtmlEscaper, Utils::OptionsUtils
Defined in:
lib/aquarium/aspects/aspect.rb

Overview

Aspect

Aspect “advises” one or more method invocations for one or more types or objects (including class methods on types). The corresponding advice is a Proc that is invoked either before the join point, after it returns, after it raises an exception, after either event, or around the join point, meaning the advice runs and it decides when and if to invoke the advised method. (Hence, around advice can run code before and after the join point call and it can “veto” the actual join point call).

See also Aquarium::DSL for more information.

Constant Summary collapse

ASPECT_CANONICAL_OPTIONS =
{
  "advice"            => %w[action do_action use_advice advise_with invoke call],
  "pointcuts"         => %w[pointcut],
  "named_pointcuts"   => %w[named_pointcut],
  "exceptions"        => %w[exception],
  "ignore_no_matching_join_points" => %w[ignore_no_jps]
}
CANONICAL_OPTIONS =
Pointcut::CANONICAL_OPTIONS.merge ASPECT_CANONICAL_OPTIONS

Constants included from Advice

Aquarium::Aspects::Advice::KINDS_IN_PRIORITY_ORDER, Aquarium::Aspects::Advice::UNKNOWN_ADVICE_KIND

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Utils::OptionsUtils

append_features, #hashify, #init_specification, universal_options, universal_prepositions, #validate_options

Methods included from Utils::ArrayUtils

#make_array, make_array, #strip_array_nils, strip_array_nils

Methods included from Utils::SetUtils

#make_set, #strip_set_nils, strip_set_nils

Methods included from Utils::HtmlEscaper

escape, #escape

Methods included from Utils::HashUtils

#make_hash, #strip_nil_keys

Methods included from DefaultObjectsHandler

#default_objects_given, #default_objects_given?, #use_default_objects_if_defined

Methods included from ExclusionHandler

#all_excluded_pointcuts, #is_excluded_join_point?, #is_excluded_method?, #is_excluded_pointcut?, #is_excluded_type_or_object?, #is_explicitly_excluded_method?, #join_point_excluded?, #matches_excluded_method_regex?, #set_calculated_excluded_pointcuts

Methods included from Advice

compare_advice_kinds, debug_backtraces, debug_backtraces=, kinds, sort_by_priority_order

Constructor Details

#initialize(*options, &block) ⇒ Aspect

Aspect.new (:around | :before | :after | :after_returning | :after_raising )

(:pointcuts => [...]), :named_pointcuts => [...] |
 ((:types => [...] | :types_and_ancestors => [...] | :types_and_descendents => [...]
  | :types_and_nested_types | :objects => [...]), 
  :methods => [], :method_options => [...],
  :attributes => [...], :attribute_options[...]),
 (:advice = advice | do |join_point, obj, *args| ...; end)

where the parameters often have many synonyms (mostly to support a “humane interface”) and they are interpreted as followed:

Type of Advice

:around

Invoke the specified advice “around” the join points. It is up to the advice itself to call join_point.proceed (where join_point is the first option passed to the advice) if it wants the advised method to actually execute.

:before

Invoke the specified advice before the join point.

:after

Invoke the specified advice after the join point either returns successfully or raises an exception.

:after_returning

Invoke the specified advice after the join point returns successfully.

:after_raising [=> exception || [exception_list]]

Invoke the specified advice after the join point raises one of the specified exceptions. If no exceptions are specified, the advice is invoked after any exception is raised. An alternative syntax is :after_raising, :exception[s] => (exception || [exception_list]).

Advice

The advice to invoke before, after, or around the join points. Only one advice may be specified. If a block is specified, the following options are ignored.

  • :advice => proc

  • :action => proc

  • :do_action => proc

  • :use_advice => proc

  • :advise_with => proc

  • :invoke => proc

  • :call => proc

Pointcuts

A Pointcut, JoinPoint, or array of the same (Mixed is allowed.). Specifying pointcuts is mutually-exclusive with specifying them “indirectly” through :types, :objects, :methods, :attributes, :method_options, and :attribute_options parameters.

  • :pointcuts => pointcut || [pointcut_list]

  • :pointcut => pointcut || [pointcut_list]

  • :on_pointcut => pointcut || [pointcut_list]

  • :on_pointcuts => pointcut || [pointcut_list]

  • :in_pointcut => pointcut || [pointcut_list]

  • :in_pointcuts => pointcut || [pointcut_list]

  • :within_pointcut => pointcut || [pointcut_list]

  • :within_pointcuts => pointcut || [pointcut_list]

Named Pointcuts

Specify search criteria to locate Pointcuts defined as class constants and/or class variables. The options for the named_pointcuts parameter must form a hash and satisfy the requirements documented for Aquarium::Finders::PointcutFinder#find. Specifying named pointcuts is also mutually-exclusive with specifying Pointcuts “indirectly” through :types, :objects, :methods, :attributes, :method_options, and :attribute_options parameters.

  • :named_pointcuts => {PointcutFinder options}

  • :named_pointcut => {PointcutFinder options}

  • :on_named_pointcuts => {PointcutFinder options}

  • :on_named_pointcut => {PointcutFinder options}

  • :in_named_pointcuts => {PointcutFinder options}

  • :in_named_pointcut => {PointcutFinder options}

  • :within_named_pointcuts => {PointcutFinder options}

  • :within_named_pointcut => {PointcutFinder options}

Exclude Pointcuts

Exclude the specified pointcuts. The exclude_ prefix can be used with any of the :pointcuts and :named_pointcuts synonyms.

  • :exclude_pointcuts => pointcut || [pointcut_list]

  • :exclude_named_pointcuts => {PointcutFinder options}

Miscellaneous Options

:ignore_no_matching_join_points => true | false

Do not issue a warning if no join points are actually matched by the aspect. By default, the value is false, meaning that a WARN-level message will be written to the log. It is usually very helpful to be warned when no matches occurred, for debugging purposes! A synonym for this option is ignore_no_jps => true | false.

For other options e.g., :types, :methods, Aspect#new accepts all the options that Pointcut#new accepts. It also accepts the “universal” options documented in Aquarium::Utils::OptionsUtils.



138
139
140
141
142
143
144
145
146
147
148
# File 'lib/aquarium/aspects/aspect.rb', line 138

def initialize *options, &block
  @first_option_that_was_method = []
  opts = rationalize options
  init_specification opts, CANONICAL_OPTIONS, (Pointcut::ATTRIBUTE_OPTIONS_VALUES + KINDS_IN_PRIORITY_ORDER) do
    finish_specification_initialization &block
  end
  init_pointcuts
  validate_specification
  return if noop
  advise_join_points
end

Instance Attribute Details

#adviceObject (readonly)

Returns the value of attribute advice.



33
34
35
# File 'lib/aquarium/aspects/aspect.rb', line 33

def advice
  @advice
end

#pointcutsObject (readonly)

Returns the value of attribute pointcuts.



33
34
35
# File 'lib/aquarium/aspects/aspect.rb', line 33

def pointcuts
  @pointcuts
end

#specificationObject (readonly)

Returns the value of attribute specification.



33
34
35
# File 'lib/aquarium/aspects/aspect.rb', line 33

def specification
  @specification
end

Instance Method Details

#eql?(other) ⇒ Boolean Also known as: ==

We have to ignore advice in the comparison. As recently discussed in ruby-users, there are very few situations. where Proc#eql? returns true.

Returns:

  • (Boolean)


177
178
179
180
# File 'lib/aquarium/aspects/aspect.rb', line 177

def eql? other
  self.object_id == other.object_id ||
    (self.class.eql?(other.class) && specification == other.specification && pointcuts == other.pointcuts)
end

#inspectObject Also known as: to_s



169
170
171
# File 'lib/aquarium/aspects/aspect.rb', line 169

def inspect
  "Aspect: {specification: #{specification.inspect}, pointcuts: #{pointcuts.inspect}, advice: #{advice.inspect}}"
end

#join_points_matchedObject



150
151
152
# File 'lib/aquarium/aspects/aspect.rb', line 150

def join_points_matched 
  get_jps :join_points_matched
end

#join_points_not_matchedObject



154
155
156
# File 'lib/aquarium/aspects/aspect.rb', line 154

def join_points_not_matched
  get_jps :join_points_not_matched
end

#unadviseObject Also known as: unadvise_join_points



158
159
160
161
162
163
164
165
# File 'lib/aquarium/aspects/aspect.rb', line 158

def unadvise
  return if noop
  @pointcuts.each do |pointcut|
    interesting_join_points(pointcut).each do |join_point|
      remove_advice_for_aspect_at join_point
    end
  end
end