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.beans.factory.config;
018
019import org.springframework.lang.Nullable;
020import org.springframework.util.Assert;
021
022/**
023 * Immutable placeholder class used for a property value object when it's
024 * a reference to another bean in the factory, to be resolved at runtime.
025 *
026 * @author Rod Johnson
027 * @author Juergen Hoeller
028 * @see BeanDefinition#getPropertyValues()
029 * @see org.springframework.beans.factory.BeanFactory#getBean(String)
030 * @see org.springframework.beans.factory.BeanFactory#getBean(Class)
031 */
032public class RuntimeBeanReference implements BeanReference {
033
034        private final String beanName;
035
036        @Nullable
037        private final Class<?> beanType;
038
039        private final boolean toParent;
040
041        @Nullable
042        private Object source;
043
044
045        /**
046         * Create a new RuntimeBeanReference to the given bean name.
047         * @param beanName name of the target bean
048         */
049        public RuntimeBeanReference(String beanName) {
050                this(beanName, false);
051        }
052
053        /**
054         * Create a new RuntimeBeanReference to the given bean name,
055         * with the option to mark it as reference to a bean in the parent factory.
056         * @param beanName name of the target bean
057         * @param toParent whether this is an explicit reference to a bean in the
058         * parent factory
059         */
060        public RuntimeBeanReference(String beanName, boolean toParent) {
061                Assert.hasText(beanName, "'beanName' must not be empty");
062                this.beanName = beanName;
063                this.beanType = null;
064                this.toParent = toParent;
065        }
066
067        /**
068         * Create a new RuntimeBeanReference to a bean of the given type.
069         * @param beanType type of the target bean
070         * @since 5.2
071         */
072        public RuntimeBeanReference(Class<?> beanType) {
073                this(beanType, false);
074        }
075
076        /**
077         * Create a new RuntimeBeanReference to a bean of the given type,
078         * with the option to mark it as reference to a bean in the parent factory.
079         * @param beanType type of the target bean
080         * @param toParent whether this is an explicit reference to a bean in the
081         * parent factory
082         * @since 5.2
083         */
084        public RuntimeBeanReference(Class<?> beanType, boolean toParent) {
085                Assert.notNull(beanType, "'beanType' must not be empty");
086                this.beanName = beanType.getName();
087                this.beanType = beanType;
088                this.toParent = toParent;
089        }
090
091
092        /**
093         * Return the requested bean name, or the fully-qualified type name
094         * in case of by-type resolution.
095         * @see #getBeanType()
096         */
097        @Override
098        public String getBeanName() {
099                return this.beanName;
100        }
101
102        /**
103         * Return the requested bean type if resolution by type is demanded.
104         * @since 5.2
105         */
106        @Nullable
107        public Class<?> getBeanType() {
108                return this.beanType;
109        }
110
111        /**
112         * Return whether this is an explicit reference to a bean in the parent factory.
113         */
114        public boolean isToParent() {
115                return this.toParent;
116        }
117
118        /**
119         * Set the configuration source {@code Object} for this metadata element.
120         * <p>The exact type of the object will depend on the configuration mechanism used.
121         */
122        public void setSource(@Nullable Object source) {
123                this.source = source;
124        }
125
126        @Override
127        @Nullable
128        public Object getSource() {
129                return this.source;
130        }
131
132
133        @Override
134        public boolean equals(@Nullable Object other) {
135                if (this == other) {
136                        return true;
137                }
138                if (!(other instanceof RuntimeBeanReference)) {
139                        return false;
140                }
141                RuntimeBeanReference that = (RuntimeBeanReference) other;
142                return (this.beanName.equals(that.beanName) && this.beanType == that.beanType &&
143                                this.toParent == that.toParent);
144        }
145
146        @Override
147        public int hashCode() {
148                int result = this.beanName.hashCode();
149                result = 29 * result + (this.toParent ? 1 : 0);
150                return result;
151        }
152
153        @Override
154        public String toString() {
155                return '<' + getBeanName() + '>';
156        }
157
158}