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; 021 022import org.springframework.aop.MethodMatcher; 023import org.springframework.aop.Pointcut; 024import org.springframework.util.Assert; 025 026/** 027 * Pointcut constants for matching getters and setters, 028 * and static methods useful for manipulating and evaluating pointcuts. 029 * 030 * <p>These methods are particularly useful for composing pointcuts 031 * using the union and intersection methods. 032 * 033 * @author Rod Johnson 034 * @author Juergen Hoeller 035 */ 036public abstract class Pointcuts { 037 038 /** Pointcut matching all bean property setters, in any class */ 039 public static final Pointcut SETTERS = SetterPointcut.INSTANCE; 040 041 /** Pointcut matching all bean property getters, in any class */ 042 public static final Pointcut GETTERS = GetterPointcut.INSTANCE; 043 044 045 /** 046 * Match all methods that <b>either</b> (or both) of the given pointcuts matches. 047 * @param pc1 the first Pointcut 048 * @param pc2 the second Pointcut 049 * @return a distinct Pointcut that matches all methods that either 050 * of the given Pointcuts matches 051 */ 052 public static Pointcut union(Pointcut pc1, Pointcut pc2) { 053 return new ComposablePointcut(pc1).union(pc2); 054 } 055 056 /** 057 * Match all methods that <b>both</b> the given pointcuts match. 058 * @param pc1 the first Pointcut 059 * @param pc2 the second Pointcut 060 * @return a distinct Pointcut that matches all methods that both 061 * of the given Pointcuts match 062 */ 063 public static Pointcut intersection(Pointcut pc1, Pointcut pc2) { 064 return new ComposablePointcut(pc1).intersection(pc2); 065 } 066 067 /** 068 * Perform the least expensive check for a pointcut match. 069 * @param pointcut the pointcut to match 070 * @param method the candidate method 071 * @param targetClass the target class 072 * @param args arguments to the method 073 * @return whether there's a runtime match 074 */ 075 public static boolean matches(Pointcut pointcut, Method method, Class<?> targetClass, Object... args) { 076 Assert.notNull(pointcut, "Pointcut must not be null"); 077 if (pointcut == Pointcut.TRUE) { 078 return true; 079 } 080 if (pointcut.getClassFilter().matches(targetClass)) { 081 // Only check if it gets past first hurdle. 082 MethodMatcher mm = pointcut.getMethodMatcher(); 083 if (mm.matches(method, targetClass)) { 084 // We may need additional runtime (argument) check. 085 return (!mm.isRuntime() || mm.matches(method, targetClass, args)); 086 } 087 } 088 return false; 089 } 090 091 092 /** 093 * Pointcut implementation that matches bean property setters. 094 */ 095 @SuppressWarnings("serial") 096 private static class SetterPointcut extends StaticMethodMatcherPointcut implements Serializable { 097 098 public static final SetterPointcut INSTANCE = new SetterPointcut(); 099 100 @Override 101 public boolean matches(Method method, Class<?> targetClass) { 102 return (method.getName().startsWith("set") && 103 method.getParameterTypes().length == 1 && 104 method.getReturnType() == Void.TYPE); 105 } 106 107 private Object readResolve() { 108 return INSTANCE; 109 } 110 } 111 112 113 /** 114 * Pointcut implementation that matches bean property getters. 115 */ 116 @SuppressWarnings("serial") 117 private static class GetterPointcut extends StaticMethodMatcherPointcut implements Serializable { 118 119 public static final GetterPointcut INSTANCE = new GetterPointcut(); 120 121 @Override 122 public boolean matches(Method method, Class<?> targetClass) { 123 return (method.getName().startsWith("get") && 124 method.getParameterTypes().length == 0); 125 } 126 127 private Object readResolve() { 128 return INSTANCE; 129 } 130 } 131 132}