Class: Seasar::Aop::S2AopFactory

Inherits:
Object
  • Object
show all
Defined in:
lib/seasar/aop/s2aop-factory.rb

Overview

アスペクトを適用したクラスを生成するファクトリクラスです。

Constant Summary collapse

@@index =
0
@@mutex =
::Mutex.new

Class Method Summary collapse

Class Method Details

.creat_method_interceptors_map(component_class, aspects) ⇒ Object

クラスの各メソッドに適用するアスペクトを分類します。

  • args

    1. Class component_class

    2. Array aspects

  • return

    • Hash



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/seasar/aop/s2aop-factory.rb', line 82

def creat_method_interceptors_map(component_class, aspects)
  methods = Seasar::Util::ClassUtil.get_aspectable_methods(component_class)
  method_interceptors_map = {}
  methods.each {|method_name|
    interceptors = []
    aspects.each {|aspect| 
      if aspect.pointcut.applicable?(method_name)
        interceptors << aspect.interceptor
      end
    }
    if 0 < interceptors.length
      method_interceptors_map[method_name] = interceptors
    end
  }
  return method_interceptors_map
end

.create(component_class, aspects) ⇒ Object

クラスにアスペクトを適用します。

  • args

    1. Class component_class

    2. Array aspects

  • return

    • Class



38
39
40
41
42
43
44
45
# File 'lib/seasar/aop/s2aop-factory.rb', line 38

def create(component_class, aspects)
  enhanced_class = S2AopFactory.generate_enhanced_class(component_class)
  method_interceptors_map = S2AopFactory.creat_method_interceptors_map(component_class, aspects)
  method_interceptors_map.each {|method_name, interceptors|
    S2AopFactory.weave_aspect(component_class, enhanced_class, method_name, interceptors)
  }
  return enhanced_class
end

.generate_enhanced_class(component_class) ⇒ Object

元のクラスを継承した新規クラスを返します。 新規クラスの名前には、「EnhancedByS2Aop###」が付加されます。

  • args

    1. Class component_class

  • return

    • Class



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/seasar/aop/s2aop-factory.rb', line 55

def generate_enhanced_class(component_class)
  #return Class.new(component_class)
  consts = component_class.name.split(/::/)
  enhanced_class_name = nil
  @@mutex.synchronize {
    enhanced_class_name = consts.pop + '_EnhancedByS2Aop_' + @@index.to_s
    @@index += 1
  }
  if consts.size == 0
    namespace = Object
  else
    namespace = eval(consts.join('::'))
  end
  clazz = Class.new(component_class)
  # TODO: should throw exception? if contant has already defined in the namespace(module)
  namespace.const_set(enhanced_class_name, clazz) unless namespace.const_defined?(enhanced_class_name)
  return clazz
end

.weave_aspect(component_class, enhanced_class, method_name, interceptors) ⇒ Object

メソッドにアスペクトを織り込みます。(メソッドをinvokeクロージャで置き換えます)

  • args

    1. Class component_class

    2. Class enhanced_class

    3. String|Symbol method_name

    4. Array interceptors

  • return

    • none



109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/seasar/aop/s2aop-factory.rb', line 109

def weave_aspect(component_class, enhanced_class, method_name, interceptors)
  enhanced_class.__send__(:define_method, method_name) {|*args, &procedure|
    invoker = MethodInvocation.new
    invoker.method = component_class.instance_method(method_name).bind(self)
    invoker.interceptors = interceptors
    invoker.enhanced_class = enhanced_class
    invoker.component_class = component_class
    invoker.args = args
    invoker.procedure = procedure
    invoker.this = self
    return invoker.proceed
  }
end