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}