001/*
002 * Copyright 2002-2012 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.target;
018
019import java.io.Serializable;
020
021import org.springframework.aop.TargetSource;
022import org.springframework.util.ObjectUtils;
023
024/**
025 * Canonical {@code TargetSource} when there is no target
026 * (or just the target class known), and behavior is supplied
027 * by interfaces and advisors only.
028 *
029 * @author Rod Johnson
030 * @author Juergen Hoeller
031 */
032public class EmptyTargetSource implements TargetSource, Serializable {
033
034        /** use serialVersionUID from Spring 1.2 for interoperability */
035        private static final long serialVersionUID = 3680494563553489691L;
036
037
038        //---------------------------------------------------------------------
039        // Static factory methods
040        //---------------------------------------------------------------------
041
042        /**
043         * The canonical (Singleton) instance of this {@link EmptyTargetSource}.
044         */
045        public static final EmptyTargetSource INSTANCE = new EmptyTargetSource(null, true);
046
047
048        /**
049         * Return an EmptyTargetSource for the given target Class.
050         * @param targetClass the target Class (may be {@code null})
051         * @see #getTargetClass()
052         */
053        public static EmptyTargetSource forClass(Class<?> targetClass) {
054                return forClass(targetClass, true);
055        }
056
057        /**
058         * Return an EmptyTargetSource for the given target Class.
059         * @param targetClass the target Class (may be {@code null})
060         * @param isStatic whether the TargetSource should be marked as static
061         * @see #getTargetClass()
062         */
063        public static EmptyTargetSource forClass(Class<?> targetClass, boolean isStatic) {
064                return (targetClass == null && isStatic ? INSTANCE : new EmptyTargetSource(targetClass, isStatic));
065        }
066
067
068        //---------------------------------------------------------------------
069        // Instance implementation
070        //---------------------------------------------------------------------
071
072        private final Class<?> targetClass;
073
074        private final boolean isStatic;
075
076
077        /**
078         * Create a new instance of the {@link EmptyTargetSource} class.
079         * <p>This constructor is {@code private} to enforce the
080         * Singleton pattern / factory method pattern.
081         * @param targetClass the target class to expose (may be {@code null})
082         * @param isStatic whether the TargetSource is marked as static
083         */
084        private EmptyTargetSource(Class<?> targetClass, boolean isStatic) {
085                this.targetClass = targetClass;
086                this.isStatic = isStatic;
087        }
088
089        /**
090         * Always returns the specified target Class, or {@code null} if none.
091         */
092        @Override
093        public Class<?> getTargetClass() {
094                return this.targetClass;
095        }
096
097        /**
098         * Always returns {@code true}.
099         */
100        @Override
101        public boolean isStatic() {
102                return this.isStatic;
103        }
104
105        /**
106         * Always returns {@code null}.
107         */
108        @Override
109        public Object getTarget() {
110                return null;
111        }
112
113        /**
114         * Nothing to release.
115         */
116        @Override
117        public void releaseTarget(Object target) {
118        }
119
120
121        /**
122         * Returns the canonical instance on deserialization in case
123         * of no target class, thus protecting the Singleton pattern.
124         */
125        private Object readResolve() {
126                return (this.targetClass == null && this.isStatic ? INSTANCE : this);
127        }
128
129        @Override
130        public boolean equals(Object other) {
131                if (this == other) {
132                        return true;
133                }
134                if (!(other instanceof EmptyTargetSource)) {
135                        return false;
136                }
137                EmptyTargetSource otherTs = (EmptyTargetSource) other;
138                return (ObjectUtils.nullSafeEquals(this.targetClass, otherTs.targetClass) && this.isStatic == otherTs.isStatic);
139        }
140
141        @Override
142        public int hashCode() {
143                return EmptyTargetSource.class.hashCode() * 13 + ObjectUtils.nullSafeHashCode(this.targetClass);
144        }
145
146        @Override
147        public String toString() {
148                return "EmptyTargetSource: " +
149                                (this.targetClass != null ? "target class [" + this.targetClass.getName() + "]" : "no target class") +
150                                ", " + (this.isStatic ? "static" : "dynamic");
151        }
152
153}