001/* 002 * Copyright 2002-2019 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.aop.support; 018 019import java.io.Serializable; 020import java.lang.reflect.Method; 021import java.util.ArrayList; 022import java.util.Arrays; 023import java.util.List; 024 025import org.springframework.lang.Nullable; 026import org.springframework.util.PatternMatchUtils; 027 028/** 029 * Pointcut bean for simple method name matches, as an alternative to regexp patterns. 030 * 031 * <p>Does not handle overloaded methods: all methods with a given name will be eligible. 032 * 033 * @author Juergen Hoeller 034 * @author Rod Johnson 035 * @author Rob Harrop 036 * @since 11.02.2004 037 * @see #isMatch 038 */ 039@SuppressWarnings("serial") 040public class NameMatchMethodPointcut extends StaticMethodMatcherPointcut implements Serializable { 041 042 private List<String> mappedNames = new ArrayList<>(); 043 044 045 /** 046 * Convenience method when we have only a single method name to match. 047 * Use either this method or {@code setMappedNames}, not both. 048 * @see #setMappedNames 049 */ 050 public void setMappedName(String mappedName) { 051 setMappedNames(mappedName); 052 } 053 054 /** 055 * Set the method names defining methods to match. 056 * Matching will be the union of all these; if any match, 057 * the pointcut matches. 058 */ 059 public void setMappedNames(String... mappedNames) { 060 this.mappedNames = new ArrayList<>(Arrays.asList(mappedNames)); 061 } 062 063 /** 064 * Add another eligible method name, in addition to those already named. 065 * Like the set methods, this method is for use when configuring proxies, 066 * before a proxy is used. 067 * <p><b>NB:</b> This method does not work after the proxy is in 068 * use, as advice chains will be cached. 069 * @param name the name of the additional method that will match 070 * @return this pointcut to allow for multiple additions in one line 071 */ 072 public NameMatchMethodPointcut addMethodName(String name) { 073 this.mappedNames.add(name); 074 return this; 075 } 076 077 078 @Override 079 public boolean matches(Method method, Class<?> targetClass) { 080 for (String mappedName : this.mappedNames) { 081 if (mappedName.equals(method.getName()) || isMatch(method.getName(), mappedName)) { 082 return true; 083 } 084 } 085 return false; 086 } 087 088 /** 089 * Return if the given method name matches the mapped name. 090 * <p>The default implementation checks for "xxx*", "*xxx" and "*xxx*" matches, 091 * as well as direct equality. Can be overridden in subclasses. 092 * @param methodName the method name of the class 093 * @param mappedName the name in the descriptor 094 * @return if the names match 095 * @see org.springframework.util.PatternMatchUtils#simpleMatch(String, String) 096 */ 097 protected boolean isMatch(String methodName, String mappedName) { 098 return PatternMatchUtils.simpleMatch(mappedName, methodName); 099 } 100 101 102 @Override 103 public boolean equals(@Nullable Object other) { 104 return (this == other || (other instanceof NameMatchMethodPointcut && 105 this.mappedNames.equals(((NameMatchMethodPointcut) other).mappedNames))); 106 } 107 108 @Override 109 public int hashCode() { 110 return this.mappedNames.hashCode(); 111 } 112 113 @Override 114 public String toString() { 115 return getClass().getName() + ": " + this.mappedNames; 116 } 117 118}