As I understand it, attributes are syntactic sugar to do "stuff". Here's a random simple example:

package Loud; use Attribute::Handlers; sub Loud :ATTR { my ($package, $symbol, $referent, $attr, $data, $phase) = @_; no strict 'refs'; # redefines subroutines given the "Loud" attribute *{$package.'::'.*{$symbol}{NAME}} = sub { # dup STDOUT and instead pipe things to another program open my $oldout, ">&STDOUT" or die "Can't dup STDOUT: + $!"; open STDOUT, "| perl -pe 'tr/a-z/A-Z/'" or die "Can't redirect STD + OUT: $!"; $| = 1; # call the original subroutine $referent->(@_); # restore STDOUT close STDOUT; open STDOUT, ">&", $oldout or die "Can't dup \$oldout: $!"; } } # ... in another file or package package main; use base qw/Loud/; # We want this function to be loud sub foo : Loud { print "Purple is a nice color.

"; } foo(); print "Don't yell!

"; [download]

The output of this program (it runs as shown above) is:

PURPLE IS A NICE COLOR. Don't yell! [download]

Catalyst uses the ActionClass attribute here to append some action (provided by RenderView.pm) to your subroutine