001/* 002 * Copyright 2002-2018 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; 020 021import org.aopalliance.aop.Advice; 022 023import org.springframework.aop.Pointcut; 024import org.springframework.lang.Nullable; 025import org.springframework.util.ObjectUtils; 026 027/** 028 * Convenient class for regexp method pointcuts that hold an Advice, 029 * making them an {@link org.springframework.aop.Advisor}. 030 * 031 * <p>Configure this class using the "pattern" and "patterns" 032 * pass-through properties. These are analogous to the pattern 033 * and patterns properties of {@link AbstractRegexpMethodPointcut}. 034 * 035 * <p>Can delegate to any {@link AbstractRegexpMethodPointcut} subclass. 036 * By default, {@link JdkRegexpMethodPointcut} will be used. To choose 037 * a specific one, override the {@link #createPointcut} method. 038 * 039 * @author Rod Johnson 040 * @author Juergen Hoeller 041 * @see #setPattern 042 * @see #setPatterns 043 * @see JdkRegexpMethodPointcut 044 */ 045@SuppressWarnings("serial") 046public class RegexpMethodPointcutAdvisor extends AbstractGenericPointcutAdvisor { 047 048 @Nullable 049 private String[] patterns; 050 051 @Nullable 052 private AbstractRegexpMethodPointcut pointcut; 053 054 private final Object pointcutMonitor = new SerializableMonitor(); 055 056 057 /** 058 * Create an empty RegexpMethodPointcutAdvisor. 059 * @see #setPattern 060 * @see #setPatterns 061 * @see #setAdvice 062 */ 063 public RegexpMethodPointcutAdvisor() { 064 } 065 066 /** 067 * Create a RegexpMethodPointcutAdvisor for the given advice. 068 * The pattern still needs to be specified afterwards. 069 * @param advice the advice to use 070 * @see #setPattern 071 * @see #setPatterns 072 */ 073 public RegexpMethodPointcutAdvisor(Advice advice) { 074 setAdvice(advice); 075 } 076 077 /** 078 * Create a RegexpMethodPointcutAdvisor for the given advice. 079 * @param pattern the pattern to use 080 * @param advice the advice to use 081 */ 082 public RegexpMethodPointcutAdvisor(String pattern, Advice advice) { 083 setPattern(pattern); 084 setAdvice(advice); 085 } 086 087 /** 088 * Create a RegexpMethodPointcutAdvisor for the given advice. 089 * @param patterns the patterns to use 090 * @param advice the advice to use 091 */ 092 public RegexpMethodPointcutAdvisor(String[] patterns, Advice advice) { 093 setPatterns(patterns); 094 setAdvice(advice); 095 } 096 097 098 /** 099 * Set the regular expression defining methods to match. 100 * <p>Use either this method or {@link #setPatterns}, not both. 101 * @see #setPatterns 102 */ 103 public void setPattern(String pattern) { 104 setPatterns(pattern); 105 } 106 107 /** 108 * Set the regular expressions defining methods to match. 109 * To be passed through to the pointcut implementation. 110 * <p>Matching will be the union of all these; if any of the 111 * patterns matches, the pointcut matches. 112 * @see AbstractRegexpMethodPointcut#setPatterns 113 */ 114 public void setPatterns(String... patterns) { 115 this.patterns = patterns; 116 } 117 118 119 /** 120 * Initialize the singleton Pointcut held within this Advisor. 121 */ 122 @Override 123 public Pointcut getPointcut() { 124 synchronized (this.pointcutMonitor) { 125 if (this.pointcut == null) { 126 this.pointcut = createPointcut(); 127 if (this.patterns != null) { 128 this.pointcut.setPatterns(this.patterns); 129 } 130 } 131 return this.pointcut; 132 } 133 } 134 135 /** 136 * Create the actual pointcut: By default, a {@link JdkRegexpMethodPointcut} 137 * will be used. 138 * @return the Pointcut instance (never {@code null}) 139 */ 140 protected AbstractRegexpMethodPointcut createPointcut() { 141 return new JdkRegexpMethodPointcut(); 142 } 143 144 @Override 145 public String toString() { 146 return getClass().getName() + ": advice [" + getAdvice() + 147 "], pointcut patterns " + ObjectUtils.nullSafeToString(this.patterns); 148 } 149 150 151 /** 152 * Empty class used for a serializable monitor object. 153 */ 154 private static class SerializableMonitor implements Serializable { 155 } 156 157}