001/*
002 * Copyright 2002-2017 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.beans.factory.support;
018
019import java.lang.reflect.Method;
020
021import org.springframework.beans.BeanMetadataElement;
022import org.springframework.lang.Nullable;
023import org.springframework.util.Assert;
024import org.springframework.util.ObjectUtils;
025
026/**
027 * Object representing the override of a method on a managed object by the IoC
028 * container.
029 *
030 * <p>Note that the override mechanism is <em>not</em> intended as a generic
031 * means of inserting crosscutting code: use AOP for that.
032 *
033 * @author Rod Johnson
034 * @author Juergen Hoeller
035 * @author Sam Brannen
036 * @since 1.1
037 */
038public abstract class MethodOverride implements BeanMetadataElement {
039
040        private final String methodName;
041
042        private boolean overloaded = true;
043
044        @Nullable
045        private Object source;
046
047
048        /**
049         * Construct a new override for the given method.
050         * @param methodName the name of the method to override
051         */
052        protected MethodOverride(String methodName) {
053                Assert.notNull(methodName, "Method name must not be null");
054                this.methodName = methodName;
055        }
056
057
058        /**
059         * Return the name of the method to be overridden.
060         */
061        public String getMethodName() {
062                return this.methodName;
063        }
064
065        /**
066         * Set whether the overridden method is <em>overloaded</em> (i.e., whether argument
067         * type matching needs to occur to disambiguate methods of the same name).
068         * <p>Default is {@code true}; can be switched to {@code false} to optimize
069         * runtime performance.
070         */
071        protected void setOverloaded(boolean overloaded) {
072                this.overloaded = overloaded;
073        }
074
075        /**
076         * Return whether the overridden method is <em>overloaded</em> (i.e., whether argument
077         * type matching needs to occur to disambiguate methods of the same name).
078         */
079        protected boolean isOverloaded() {
080                return this.overloaded;
081        }
082
083        /**
084         * Set the configuration source {@code Object} for this metadata element.
085         * <p>The exact type of the object will depend on the configuration mechanism used.
086         */
087        public void setSource(@Nullable Object source) {
088                this.source = source;
089        }
090
091        @Override
092        @Nullable
093        public Object getSource() {
094                return this.source;
095        }
096
097        /**
098         * Subclasses must override this to indicate whether they <em>match</em> the
099         * given method. This allows for argument list checking as well as method
100         * name checking.
101         * @param method the method to check
102         * @return whether this override matches the given method
103         */
104        public abstract boolean matches(Method method);
105
106
107        @Override
108        public boolean equals(@Nullable Object other) {
109                if (this == other) {
110                        return true;
111                }
112                if (!(other instanceof MethodOverride)) {
113                        return false;
114                }
115                MethodOverride that = (MethodOverride) other;
116                return (ObjectUtils.nullSafeEquals(this.methodName, that.methodName) &&
117                                ObjectUtils.nullSafeEquals(this.source, that.source));
118        }
119
120        @Override
121        public int hashCode() {
122                int hashCode = ObjectUtils.nullSafeHashCode(this.methodName);
123                hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.source);
124                return hashCode;
125        }
126
127}