如何以面向对象方式在Perl主脚本与模块间共享Log4perl日志对象
在Perl主脚本和模块中统一使用Log4perl(面向对象方式)
当然可以实现啦!你想要在主脚本和模块里共用同一个Log4perl日志对象的需求完全合理,而且用面向对象的方式很容易做到。我给你两种可行的方案,结合你的代码示例来修改:
方法一:构造对象时传递日志对象(最贴合你的OO需求)
这是最直接的面向对象做法——让Rotation类在创建实例时接收主脚本的日志对象,把它存在实例的属性里,之后模块里的方法就能直接调用这个对象打日志了。
修改后的主脚本
先修正你原代码里的小语法错误,然后在创建Rotation实例时传入日志对象:
use strict; use warnings; use Log::Log4perl; use rotate_action; # 初始化日志对象(保留你的原逻辑,补充了日志级别设置) my $logger = Log::Log4perl->get_logger(); my $appender_log = Log::Log4perl::Appender->new( "Log::Dispatch::File", filename => "action.log", mode => "append" ); $logger->add_appender($appender_log); # 注意:默认日志级别是WARN,要显式设置INFO才能打出info级别的日志 $logger->level($Log::Log4perl::INFO); $logger->info("Logger activated"); # 创建Rotation对象时,把主脚本的logger传进去 my $ro = Rotation->new( logger => $logger ); my $file = "somefile"; # 修正原代码的语法错误:添加=号 $logger->info("processing $file"); $ro->process_file($file); $logger->info("finished processing $file"); # 修正原代码的语法错误:闭合引号
修改后的rotate_action.pm模块
调整new方法来接收并存储日志对象,之后在process_file里直接使用这个属性:
{ package Rotation; use strict; use warnings; sub new { my $class = shift; my %args = @_; # 接收传入的参数哈希 my $self = { logger => $args{logger}, # 将日志对象存入实例属性 }; bless $self, $class; return $self; } sub process_file { my $self = shift; my $file = shift; my $exec_string = "identify -format \"orientation: %[orientation]\ngeometry: %g\n\""; $exec_string .= " $file"; my $exec_result = `$exec_string 2>&1`; my $err_lvl = $?; if ($err_lvl != 0) { # 调用实例中存储的日志对象打warn日志 $self->{logger}->warn("$file is not an image"); } else { # 同样调用同一个日志对象打info日志 $self->{logger}->info("rotate $file"); `rotate.sh $file`; } } }
方法二:使用Log4perl的分类日志(无需显式传递对象)
如果你不需要给不同的Rotation实例分配不同的日志对象,Log4perl自带的分类日志机制会更简洁。它能按包名自动关联日志配置,不用手动传递对象:
修改后的主脚本(用配置初始化日志)
use strict; use warnings; use Log::Log4perl; # 用配置字符串初始化整个应用的日志规则(也可以用外部配置文件) my $log_conf = q( log4perl.rootLogger = INFO, FileAppender log4perl.appender.FileAppender = Log::Dispatch::File log4perl.appender.FileAppender.filename = action.log log4perl.appender.FileAppender.mode = append # 配置日志格式,包含时间、级别、消息 log4perl.appender.FileAppender.layout = Log::Log4perl::Layout::PatternLayout log4perl.appender.FileAppender.layout.ConversionPattern = %d %p %m%n ); Log::Log4perl->init(\$log_conf); my $logger = Log::Log4perl->get_logger(); $logger->info("Logger activated"); use rotate_action; my $ro = Rotation->new; my $file = "somefile"; $logger->info("processing $file"); $ro->process_file($file); $logger->info("finished processing $file");
修改后的rotate_action.pm模块
直接在模块里获取当前包的日志对象,它会自动继承主脚本的配置:
{ package Rotation; use strict; use warnings; use Log::Log4perl; sub new { my $class = shift; my $self = {}; bless $self, $class; return $self; } sub process_file { my $self = shift; my $file = shift; # 获取当前包对应的日志对象,自动使用主脚本的配置 my $logger = Log::Log4perl->get_logger(__PACKAGE__); my $exec_string = "identify -format \"orientation: %[orientation]\ngeometry: %g\n\""; $exec_string .= " $file"; my $exec_result = `$exec_string 2>&1`; my $err_lvl = $?; if ($err_lvl != 0) { $logger->warn("$file is not an image"); } else { $logger->info("rotate $file"); `rotate.sh $file`; } } }
两种方案各有优势:第一种完全是面向对象的思路,适合需要给不同实例定制日志对象的场景;第二种更简洁,适合整个应用日志规则统一的情况。你可以根据自己的需求选择~
内容的提问来源于stack exchange,提问作者d-nnis
相关产品推荐
相关产品推荐

