class Aspector::Interception
Constants
- METHOD_TEMPLATE
Attributes
aspect[R]
options[R]
target[R]
Public Class Methods
new(aspect, target, options)
click to toggle source
# File lib/aspector/interception.rb, line 7 def initialize aspect, target, options @aspect = aspect @target = target @options = options @wrapped_methods = {} end
Public Instance Methods
advices()
click to toggle source
# File lib/aspector/interception.rb, line 18 def advices @aspect.class.advices end
apply()
click to toggle source
# File lib/aspector/interception.rb, line 26 def apply invoke_deferred_logics define_methods_for_advice_blocks add_to_instances unless @options[:existing_methods_only] apply_to_methods unless @options[:new_methods_only] add_method_hooks unless @options[:existing_methods_only] # TODO: clear deferred logic results if they are not used in any advice return end
apply_to_method(method, scope = nil)
click to toggle source
# File lib/aspector/interception.rb, line 68 def apply_to_method method, scope = nil filtered_advices = filter_advices advices, method return if filtered_advices.empty? logger.debug 'apply-to-method', method scope ||= if context.private_instance_methods.include?(method.to_sym) :private elsif context.protected_instance_methods.include?(method.to_sym) :protected else :public end recreate_method method, filtered_advices, scope end
apply_to_methods()
click to toggle source
# File lib/aspector/interception.rb, line 36 def apply_to_methods return if advices.empty? # If method/methods option is set and all are String or Symbol, apply to those only, instead of # iterating through all methods methods = [@options[:method] || @options[:methods]] methods.compact! methods.flatten! if not methods.empty? and methods.all?{|method| method.is_a? String or method.is_a? Symbol } methods.each do |method| apply_to_method(method.to_s) end return end context.public_instance_methods.each do |method| apply_to_method(method.to_s, :public) end context.protected_instance_methods.each do |method| apply_to_method(method.to_s, :protected) end if @options[:private_methods] context.private_instance_methods.each do |method| apply_to_method(method.to_s, :private) end end end
disabled?()
click to toggle source
# File lib/aspector/interception.rb, line 14 def disabled? @aspect.disabled? end
logger()
click to toggle source
# File lib/aspector/interception.rb, line 22 def logger @logger ||= Logging.get_logger(self) end
Private Instance Methods
add_method_hooks()
click to toggle source
# File lib/aspector/interception.rb, line 137 def add_method_hooks return if advices.empty? if @options[:class_methods] return unless @target.is_a?(Module) eigen_class = class << @target; self; end orig_singleton_method_added = @target.method(:singleton_method_added) eigen_class.send :define_method, :singleton_method_added do |method| aop_singleton_method_added(method) do orig_singleton_method_added.call(method) end end else eigen_class = class << @target; self; end if @target.is_a? Module orig_method_added = @target.method(:method_added) else orig_method_added = eigen_class.method(:method_added) end eigen_class.send :define_method, :method_added do |method| aop_method_added(method) do orig_method_added.call(method) end end end end
add_to_instances()
click to toggle source
# File lib/aspector/interception.rb, line 126 def add_to_instances return if advices.empty? aspect_instances = context.instance_variable_get(:@aop_instances) unless aspect_instances aspect_instances = AspectInstances.new context.instance_variable_set(:@aop_instances, aspect_instances) end aspect_instances << self end
context()
click to toggle source
context is where advices will be applied (i.e. where methods are modified), can be different from target
# File lib/aspector/interception.rb, line 97 def context return @target if @target.is_a?(Module) and not @options[:class_methods] class << @target self end end
deferred_logic_results(logic)
click to toggle source
# File lib/aspector/interception.rb, line 88 def deferred_logic_results logic @deferred_logic_results[logic] end
define_methods_for_advice_blocks()
click to toggle source
# File lib/aspector/interception.rb, line 117 def define_methods_for_advice_blocks advices.each do |advice| next if advice.raw? next unless advice.advice_block context.send :define_method, advice.with_method, advice.advice_block context.send :private, advice.with_method end end
filter_advices(advices, method)
click to toggle source
# File lib/aspector/interception.rb, line 168 def filter_advices advices, method advices.select do |advice| advice.match?(method, self) end end
get_wrapped_method_of(method)
click to toggle source
# File lib/aspector/interception.rb, line 92 def get_wrapped_method_of method @wrapped_methods[method] end
invoke_deferred_logics()
click to toggle source
# File lib/aspector/interception.rb, line 105 def invoke_deferred_logics return unless (logics = @aspect.class.send :_deferred_logics_) logics.each do |logic| result = logic.apply context, aspect if advices.detect {|advice| advice.use_deferred_logic? logic } @deferred_logic_results ||= {} @deferred_logic_results[logic] = result end end end
recreate_method(method, advices, scope)
click to toggle source
# File lib/aspector/interception.rb, line 174 def recreate_method method, advices, scope context.instance_variable_set(:@aop_creating_method, true) raw_advices = advices.select {|advice| advice.raw? } if raw_advices.size > 0 raw_advices.each do |advice| if @target.is_a? Module and not @options[:class_methods] @target.class_exec method, self, &advice.advice_block else @target.instance_exec method, self, &advice.advice_block end end return if raw_advices.size == advices.size end begin @wrapped_methods[method] = context.instance_method(method) rescue # ignore undefined method error if @options[:existing_methods_only] logger.log Logging::WARN, 'method-not-found', method end return end before_advices = advices.select {|advice| advice.before? || advice.before_filter? } after_advices = advices.select {|advice| advice.after? } around_advices = advices.select {|advice| advice.around? } (around_advices.size - 1).downto(1) do |i| advice = around_advices[i] recreate_method_with_advices method, [], [], advice end recreate_method_with_advices method, before_advices, after_advices, around_advices.first, true context.send scope, method if scope != :public ensure context.send :remove_instance_variable, :@aop_creating_method end
recreate_method_with_advices(method, before_advices, after_advices, around_advice, is_outermost = false)
click to toggle source
# File lib/aspector/interception.rb, line 218 def recreate_method_with_advices method, before_advices, after_advices, around_advice, is_outermost = false aspect = @aspect logger = @logger interception = self orig_method = get_wrapped_method_of method code = METHOD_TEMPLATE.result(binding) logger.debug 'generate-code', method, code context.class_eval code, __FILE__, __LINE__ + 4 end