ConfigurationClass.java 5.6 KB
Newer Older
1
/*
C
Chris Beams 已提交
2
 * Copyright 2002-2009 the original author or authors.
3 4 5 6 7 8 9 10 11 12 13 14 15
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
C
Chris Beams 已提交
16

17
package org.springframework.context.annotation.support;
18 19 20 21 22 23 24

import static java.lang.String.*;

import java.lang.reflect.Modifier;
import java.util.HashSet;
import java.util.Set;

25 26
import org.springframework.beans.factory.parsing.Problem;
import org.springframework.beans.factory.parsing.ProblemReporter;
27 28
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
29 30 31 32
import org.springframework.util.Assert;


/**
33
 * Represents a user-defined {@link Configuration @Configuration} class.
34 35 36 37
 * Includes a set of {@link Bean} methods, including all such methods defined in the
 * ancestry of the class, in a 'flattened-out' manner. Note that each {@link BeanMethod}
 * representation contains source information about where it was originally detected
 * (for the purpose of tooling with Spring IDE).
38 39
 * 
 * @author Chris Beams
40 41 42
 * @see ConfigurationModel
 * @see BeanMethod
 * @see ConfigurationParser
43
 */
44
final class ConfigurationClass extends ModelClass {
45

46 47
	private String beanName;
	private int modifiers;
48
	private Configuration configurationAnnotation;
49
	private HashSet<BeanMethod> methods = new HashSet<BeanMethod>();
50 51 52 53 54 55
	private ConfigurationClass declaringClass;

	public String getBeanName() {
		return beanName == null ? getName() : beanName;
	}

56
	public void setBeanName(String id) {
57 58 59
		this.beanName = id;
	}

60 61
	public int getModifiers() {
		return modifiers;
62 63
	}

64 65 66
	public void setModifiers(int modifiers) {
		Assert.isTrue(modifiers >= 0, "modifiers must be non-negative");
		this.modifiers = modifiers;
67 68
	}

69 70
	public Configuration getConfigurationAnnotation() {
		return this.configurationAnnotation;
71 72
	}

73 74 75
	public void setConfigurationAnnotation(Configuration configAnno) {
		Assert.notNull(configAnno, "configuration annotation must be non-null");
		this.configurationAnnotation = configAnno;
76 77
	}

78 79
	public Set<BeanMethod> getBeanMethods() {
		return methods;
80 81
	}

82 83 84
	public ConfigurationClass addBeanMethod(BeanMethod method) {
		method.setDeclaringClass(this);
		methods.add(method);
85 86 87
		return this;
	}

88 89
	public ConfigurationClass getDeclaringClass() {
		return declaringClass;
90 91
	}

92 93
	public void setDeclaringClass(ConfigurationClass configurationClass) {
		this.declaringClass = configurationClass;
94 95
	}

96
	public void validate(ProblemReporter problemReporter) {
97
		// configuration classes must be annotated with @Configuration
98
		if (configurationAnnotation == null)
99
			problemReporter.error(new NonAnnotatedConfigurationProblem());
100 101 102

		// a configuration class may not be final (CGLIB limitation)
		if (Modifier.isFinal(modifiers))
103
			problemReporter.error(new FinalConfigurationProblem());
104

105
		for (BeanMethod method : methods)
106
			method.validate(problemReporter);
107 108 109 110 111 112 113 114 115 116 117 118 119
	}

	@Override
	public String toString() {
		return format("%s; modifiers=%d; methods=%s", super.toString(), modifiers, methods);
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = super.hashCode();
		result = prime * result + ((declaringClass == null) ? 0 : declaringClass.hashCode());
		result = prime * result + ((beanName == null) ? 0 : beanName.hashCode());
120
		result = prime * result + ((configurationAnnotation == null) ? 0 : configurationAnnotation.hashCode());
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
		result = prime * result + ((methods == null) ? 0 : methods.hashCode());
		result = prime * result + modifiers;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (!super.equals(obj))
			return false;
		if (getClass() != obj.getClass())
			return false;
		ConfigurationClass other = (ConfigurationClass) obj;
		if (declaringClass == null) {
			if (other.declaringClass != null)
				return false;
		} else if (!declaringClass.equals(other.declaringClass))
			return false;
		if (beanName == null) {
			if (other.beanName != null)
				return false;
		} else if (!beanName.equals(other.beanName))
			return false;
145 146
		if (configurationAnnotation == null) {
			if (other.configurationAnnotation != null)
147
				return false;
148
		} else if (!configurationAnnotation.equals(other.configurationAnnotation))
149 150 151 152 153 154 155 156 157 158 159 160 161
			return false;
		if (methods == null) {
			if (other.methods != null)
				return false;
		} else if (!methods.equals(other.methods))
			return false;
		if (modifiers != other.modifiers)
			return false;
		return true;
	}


	/** Configuration classes must be annotated with {@link Configuration @Configuration}. */
162
	class NonAnnotatedConfigurationProblem extends Problem {
163

164
		NonAnnotatedConfigurationProblem() {
165 166 167
			super(format("%s was specified as a @Configuration class but was not actually annotated " +
			             "with @Configuration. Annotate the class or do not attempt to process it.",
			             getSimpleName()),
168
			      ConfigurationClass.this.getLocation());
169
		}
170

171 172
	}

C
Chris Beams 已提交
173

174
	/** Configuration classes must be non-final to accommodate CGLIB subclassing. */
175
	class FinalConfigurationProblem extends Problem {
176

177
		FinalConfigurationProblem() {
178
			super(format("@Configuration class [%s] may not be final. Remove the final modifier to continue.",
179 180
			             getSimpleName()),
			      ConfigurationClass.this.getLocation());
181
		}
182

183 184
	}

185
}