Matchers that are passed as arguments to include()
method of spy definition objects can be created using spy.byXXX()
functions. There are several functions that can create various types of matchers - see below.
Matchers have some methods that alter their behavior. As matchers are immutable, all those methods return new, altered matches instead of changing old ones:
m.noConstructors()
- excludes constructors and static constructors;m.noAccessors()
- excludes accessor methods:getXXX()
andsetXXX(v)
;m.noCommons()
- excludes known common methods:toString()
,equals()
,hashCode()
andvalueOf()
;m.forTrace()
- equivalent ofm.noConstructors().noAccessors().noCommons()
, suitable for tracer;
Both spy and tracer use the same matcher objects. For spy definitions, use .include()
and .exclude()
methods. Tracer has two functions: tracer.include()
and tracer.exclude()
that can be used to configure which classes and methods should (not) be traced.
spy.byMethod()
spy.byMethod(classPattern, methodPattern)
spy.byMethod(access, classPattern, methodPattern, returnType, String...argTypes)
These matchers will choose which classes and methods will be instrumented. Both classPattern
and methodPattern
can contain asterisk (*
) or double asterisk (**
) which has the same meaning as in Ant or Maven: single asterisk will choose all classes in given package (eg. org.jboss.*
), and double asterisk will choose all classes in given package and all subpackages it contains. For method names single asterisk represents any sequence of characters (double asterisk makes no sense in method names).
First (short) version of byMethod()
will choose all public methods matching patterns passed as its arguments, full version of byMethod()
allows for much finer control: it is possible to pass access flags (eg. choosing only static methods etc.) and define return type and types of arguments (as in java - eg. int
, void
, String
, com.mycompany.MyClass
etc.).
spy.byInterfaceAndMethod()
spy.byInterfaceAndMethod(classPattern, methodPattern)
spy.byInterfaceAndMethod(access, classPattern, methodPattern, returnType, String...argTypes)
These matchers will choose classes by interfaces they implement. Only direct implementations are supported at this time. Matchers will choose all methods of a class implementing an interface, not only interface methods - this decoupling makes matching by marker interface possible. Besides interface parts, these functions work the same as spy.byMethod()
.
spy.byClassAnnotation()
spy.byClassAnnotation(classAnnotation)
spy.byClassAnnotation(classAnnotation, methodPattern)
spy.byMethodAnnotation(classPattern, methodAnnotation)
spy.byClassMethodAnnotation(classAnnotation, methodAnnotation)
These matchers will choose classes that are annotated by classAnnotation
and methods matching methodPattern
or all methods except constructors if method pattern has not been specified. Third and fourth variant allows matching also by method annotations. These matchers are useful in some cases, for example when looking for all EJB beans of certain type.
spy.byClass()
spy.byClass(classPattern)
Matches all public methods of all classes whose names match classPattern
.
spy.byInterface()
spy.byInterface(interfacePattern)
Matches all public methods of all classes implementing interfaces whose names match interfacePattern
.
Simplified matchers
Some functions that accept matchers (eg. tracer.include()
, tracer.exclude()
, SpyDefinition.include()
) also accept strings as alternative to matcher objects. This makes defining of class inclusions/exclusions cleaner and less tedious. Class matching strings should have the following syntax:
my.app.MyClass
my.app.MyClass/myMethod
999:my.app.MyClass/myMethod
It consists of class name pattern (ant-like *
and **
masks can be used), optional prefix indicating priority (in nnn:
form) and optional suffix indicating method name or mask (ant-like masks also work here). In addition both class and method names can be specified using regular expressions prefixes by tilde (~
).