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.Arrays; 022import java.util.LinkedList; 023import java.util.List; 024 025import org.springframework.util.ObjectUtils; 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 LinkedList<String>(); 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 LinkedList<String>(); 061 if (mappedNames != null) { 062 this.mappedNames.addAll(Arrays.asList(mappedNames)); 063 } 064 } 065 066 /** 067 * Add another eligible method name, in addition to those already named. 068 * Like the set methods, this method is for use when configuring proxies, 069 * before a proxy is used. 070 * <p><b>NB:</b> This method does not work after the proxy is in 071 * use, as advice chains will be cached. 072 * @param name name of the additional method that will match 073 * @return this pointcut to allow for multiple additions in one line 074 */ 075 public NameMatchMethodPointcut addMethodName(String name) { 076 this.mappedNames.add(name); 077 return this; 078 } 079 080 081 @Override 082 public boolean matches(Method method, Class<?> targetClass) { 083 for (String mappedName : this.mappedNames) { 084 if (mappedName.equals(method.getName()) || isMatch(method.getName(), mappedName)) { 085 return true; 086 } 087 } 088 return false; 089 } 090 091 /** 092 * Return if the given method name matches the mapped name. 093 * <p>The default implementation checks for "xxx*", "*xxx" and "*xxx*" matches, 094 * as well as direct equality. Can be overridden in subclasses. 095 * @param methodName the method name of the class 096 * @param mappedName the name in the descriptor 097 * @return if the names match 098 * @see org.springframework.util.PatternMatchUtils#simpleMatch(String, String) 099 */ 100 protected boolean isMatch(String methodName, String mappedName) { 101 return PatternMatchUtils.simpleMatch(mappedName, methodName); 102 } 103 104 105 @Override 106 public boolean equals(Object other) { 107 return (this == other || (other instanceof NameMatchMethodPointcut && 108 ObjectUtils.nullSafeEquals(this.mappedNames, ((NameMatchMethodPointcut) other).mappedNames))); 109 } 110 111 @Override 112 public int hashCode() { 113 return (this.mappedNames != null ? this.mappedNames.hashCode() : 0); 114 } 115 116}