我有一个Moose BaseDBModel,它有不同的子类映射到数据库中的表。子类中的所有方法都类似于“get_xxx”或“update_xxx”,它指的是不同的数据库操作。
现在我想为所有这些方法实现一个缓存系统,所以我的想法是“之前”所有名为“get_xxx”的方法,我将搜索方法的名称作为我的memcache池中的键值。如果我找到了值,那么我将直接返回值而不是方法。
理想情况下,我的代码就像这样
BaseDBModel
package Speed::Module::BaseDBModel;
use Moose;
sub BUILD {
my $self = shift;
for my $method ($self->meta->get_method_list()){
if($method =~ /^get_/){
$self->meta->add_before_method_modifier($method,sub {
warn $method;
find_value_by_method_name($method);
[return_value_if_found_value]
});
}
}
}
子类示例1
package Speed::Module::Character;
use Moose;
extends 'Speed::Module::BaseDBModel';
method get_character_by_id {
xxxx
}
现在我的问题是,当我的程序运行时,它会反复修改方法,例如:
重启apache
访问将调用get_character_by_id的页面,这样我就可以看到一条警告消息
代码:
my $db_character = Speed::Module::Character->new(glr => $self->glr);
$character_state = $db_character->get_character_by_id($cid);
警告:
get_character_by_id at /Users/dyk/Sites/speed/lib/Speed/Module/BaseDBModel.pm line 60.
但是如果我刷新页面,我看到了2条警告信息
警告:
get_character_by_id at /Users/dyk/Sites/speed/lib/Speed/Module/BaseDBModel.pm line 60.
get_character_by_id at /Users/dyk/Sites/speed/lib/Speed/Module/BaseDBModel.pm line 60.
我正在使用带有apache的mod_perl 2.0,每次刷新页面时,我的get_character_by_id方法都会被修改,我不想要
答案 0 :(得分:0)
每次构建新实例时,你的BUILD是不是在执行add_before?我不确定那是你想要的。
嗯,简单/笨重的方法是设置一些包级别标志,这样你只需要做一次。
否则,我想你想要加入Moose自己的属性构建。看看这个:http://www.perlmonks.org/?node_id=948231
答案 1 :(得分:0)
问题是BUILD
每次创建对象时都会运行(即每次->new()
次调用后),但add_before_method_modifier
会将修饰符添加到类,即所有对象。
请注意,每次use
调用import来自已使用过的包。那是你想要添加修饰符的地方。
父:
package Parent;
use Moose;
sub import {
my ($class) = @_;
foreach my $method ($class->meta->get_method_list) {
if ($method =~ /^get_/) {
$class->meta->add_before_method_modifier($method, sub {
warn $method
});
}
}
}
1;
Child1:
package Child1;
use Moose;
extends 'Parent';
sub get_a { 'a' }
1;
CHILD2:
package Child2;
use Moose;
extends 'Parent';
sub get_b { 'b' }
1;
所以现在它按预期工作:
$ perl -e 'use Child1; use Child2; Child1->new->get_a; Child2->new->get_b; Child1->new->get_a;'
get_a at Parent.pm line 11.
get_b at Parent.pm line 11.
get_a at Parent.pm line 11.
由于您无法100%确定将import
被调用(因为您无法确定将使用use
)更简洁明了的解决方案只需添加类似{{{ 1}}在每个派生类中。
use My::Getter::Cacher
在这种情况下,每个派生类都应包含package My::Getter::Cacher;
sub import {
my $class = [caller]->[0];
# ...
}
和extends 'Parent'
,因为第一行是关于继承,而第二行是关于在修饰符之前添加。你可能会认为它有点多余,但正如我所说,我相信它更清洁,更直接。
也许你应该看一下Memoize模块。