我处理的是一个提供DBI
抽象的模块,它自动重新连接。我需要在`DBI-> connect。
有没有办法在不修改此模块的情况下添加钩子?我在文档中找不到运气。我错过了什么?
答案 0 :(得分:3)
DBI文档有a chapter about subclassing,其中提到了$dbh->connected
方法,它什么都不做。这似乎正是你想要的。
当使用子类化时,在成功进行新连接后,DBI-> connect方法会自动调用:
$dbh->connected($dsn, $user, $pass, \%attr);
我还没有尝试过,但它可能只需将这个连接的方法直接修补到DBI中而不需要子类化任何东西。 In connect
there is definitely a call to connected
。
但是我不知道在哪里修补它。可能是驱动程序。快速grep of the cpan表明DBI dist中只包含两个驱动程序包括此内容。 DBD::Gofer和DBD::Proxy,但那个是空的。它们都在DBD::<drivername>::db
包中。
假设您正在使用MySQL,那么您可以将其挂钩到您的驱动程序中。通过继承和使用该驱动程序,或者简单地将其修补。
*DBD::mysql::db::connected = sub {
my ($dbh, dsn, $user, $pass, $attr, $old_driver) = @_;
warn 'Connected!';
}
这应该与其他驱动程序一样,除非它们有自己的connected
。在这种情况下,您应该手动将其包装起来或使用类似Class::Method::Modifiers的around
之类的内容来包装它,以确保原始行为保持不变。
此时您还有实际连接的$dbh
,因此如果您愿意,可以在connected
的数据库中搜索。
当然,这会在每次连接之后给你回调。如果你只想获得重新连接,你可以在词法变量上创建一个闭包来计算连接并跳过第一个连接。
{
my $connection_counter;
*DBD::mysql::db::connected = sub {
my ($dbh, dsn, $user, $pass, $attr, $old_driver) = @_;
return unless $connection_counter++; # skip first connection
warn 'Connected!';
}
}
请注意,我没有对此进行任何测试。