• No results found

Fortunately, AspectJ allows the use of name patterns through the * character. The * is actually a special type name and can be used to match all types, includ- ing primitive types as needed. In addition, the * can be used to match zero or more characters except for “.”. Using this information, we can combine the two join points into one:

call(private void DVD.set*(*))

Notice the need for two * wildcards. The first wildcard used in the set* portion tells the system to match all methods that are defined as access private, that return void, that belong to the DVD class, and that have a method name starting with the text “set” followed by any number of additional characters (except the “.”). Based on the earlier code for setLocation() and setCount(), these two methods would match so far. However, notice that both of the methods have different parameter types passed to them. Without the second wildcard, this would cause a problem in the join point. The second wildcard tells the system to continue matching methods as long as they have a single parameter of any type. If one of the methods is changed to have zero parameters or more than 1, the signature will not be triggered on that particular join point because it won’t match.

In another example, suppose we are interested in all the methods defined within the DVD class that have a single parameter. The signature is

call(private void DVD.*(*))

AspectJ Join Points

This signature matches all private methods defined within the DVD class having a single parameter. This example can be expanded to match all methods regard- less of access type:

call(* void DVD.*(*))

In this signature, we’ve replaced the access type with a wildcard indicating that join points within the application should be matched regardless of whether they are defined as public, protected, or private. Further, we can eliminate the return type and replace it with a wildcard as well:

call(* * DVD.*(*))

Here we are matching all methods within the DVD class having a single param- eter. If there is no class type defined in a signature, the system will assume you mean any class within the application should be used for matching join points. Next, any class can be used:

call(* * *.*(*))

In this signature, the class type has been replaced with a wildcard. Now all methods will be matched across all classes used in an example application. However, in all your examples, a single parameter is matched because of the wildcard. This signature will not match methods with two parameters. An addi- tional wildcard is available in AspectJ to handle this situation as well as several others.

AspectJ has a wildcard, “..”, which can be used to match any sequence of char- acters as well as act as a wildcard for parameter counts within matching para- meters. Take, for example, the following methods:

private void setCount(int inCount) { count = inCount;

}

private void setLocation(String inLocation) { location = inLocation;

}

private void setStats(String inLocation, int inCount) { setCount(inCount);

setLocation(inLocation); }

To match all these methods, we can use the following signature:

call(private void DVD.set*(..))

This signature matches all three of the earlier methods, including the one with two parameters. The “..” wildcard, when not used in the parameter part of a call or execution join point, can be used to match any sequence of characters that start and end with a period. As an example of using the “..” wildcard as well as

matching types within a package, let’s assume there is a package hierarchy defined as

com.company.department.room.class1 com.company.department.room.class2 com.company.department.room.class3

As we see in the next chapter, a pointcut designator called target is triggered when a class is a target during execution. There will be times when join points need to be defined based on specific classes in a package. As a start, we can specify that a join point be triggered when the class1 class defined earlier is a target in the execution of a program. The signature might look like this:

target(com.company.department.room.class1)

If we want to target any of the classes within the com.company.department. room path, we can use this signature:

target(com.company.department.room.*)

This signature matches all three class types: class1, class2, and class3. If we use the * wildcard (as in the signature we just created), the system assumes that there will be no types between room and the actual class. What if we want to match inner class types, such as com.company.department? In that case, we need to use the “..” wildcard. For example:

target(com.company..*)

This signature matches all class types that begin with the path com.company. If you know all the possible inner types, you could also write the signature as

target(com.company.*.*.*)

Finally, the wildcards can be used along with package definitions in a signature like the following example:

call(public * com.company.department.room.*.*(..)

This signature matches all public methods with any number of parameters and any return type belonging to any class defined in the com.company. department.room hierarchy. Using our example classes above, this signature matches any public methods in class1, class2, and class3. Inner classes can also be part of a signature for a method call join point. For example:

call(private * com.company.department..*(..)

This signature matches all private methods with any return type and part of the com.company.department package hierarchy. The methods can have any type and number of parameters.

AspectJ Join Points