spring MetadataGenerationEnvironment 源码
springboot MetadataGenerationEnvironment 代码
文件路径:/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/MetadataGenerationEnvironment.java
/*
* Copyright 2012-2022 the original author or authors.
*
* 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
*
* https://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.
*/
package org.springframework.boot.configurationprocessor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import org.springframework.boot.configurationprocessor.fieldvalues.FieldValuesParser;
import org.springframework.boot.configurationprocessor.fieldvalues.javac.JavaCompilerFieldValuesParser;
import org.springframework.boot.configurationprocessor.metadata.ItemDeprecation;
/**
* Provide utilities to detect and validate configuration properties.
*
* @author Stephane Nicoll
*/
class MetadataGenerationEnvironment {
private static final String NULLABLE_ANNOTATION = "org.springframework.lang.Nullable";
private static final Set<String> TYPE_EXCLUDES;
static {
Set<String> excludes = new HashSet<>();
excludes.add("com.zaxxer.hikari.IConnectionCustomizer");
excludes.add("groovy.lang.MetaClass");
excludes.add("groovy.text.markup.MarkupTemplateEngine");
excludes.add("java.io.Writer");
excludes.add("java.io.PrintWriter");
excludes.add("java.lang.ClassLoader");
excludes.add("java.util.concurrent.ThreadFactory");
excludes.add("jakarta.jms.XAConnectionFactory");
excludes.add("javax.sql.DataSource");
excludes.add("javax.sql.XADataSource");
excludes.add("org.apache.tomcat.jdbc.pool.PoolConfiguration");
excludes.add("org.apache.tomcat.jdbc.pool.Validator");
excludes.add("org.flywaydb.core.api.callback.FlywayCallback");
excludes.add("org.flywaydb.core.api.resolver.MigrationResolver");
TYPE_EXCLUDES = Collections.unmodifiableSet(excludes);
}
private final TypeUtils typeUtils;
private final Elements elements;
private final Messager messager;
private final FieldValuesParser fieldValuesParser;
private final Map<TypeElement, Map<String, Object>> defaultValues = new HashMap<>();
private final String configurationPropertiesAnnotation;
private final String nestedConfigurationPropertyAnnotation;
private final String deprecatedConfigurationPropertyAnnotation;
private final String constructorBindingAnnotation;
private final String defaultValueAnnotation;
private final Set<String> endpointAnnotations;
private final String readOperationAnnotation;
private final String nameAnnotation;
private final String autowiredAnnotation;
MetadataGenerationEnvironment(ProcessingEnvironment environment, String configurationPropertiesAnnotation,
String nestedConfigurationPropertyAnnotation, String deprecatedConfigurationPropertyAnnotation,
String constructorBindingAnnotation, String autowiredAnnotation, String defaultValueAnnotation,
Set<String> endpointAnnotations, String readOperationAnnotation, String nameAnnotation) {
this.typeUtils = new TypeUtils(environment);
this.elements = environment.getElementUtils();
this.messager = environment.getMessager();
this.fieldValuesParser = resolveFieldValuesParser(environment);
this.configurationPropertiesAnnotation = configurationPropertiesAnnotation;
this.nestedConfigurationPropertyAnnotation = nestedConfigurationPropertyAnnotation;
this.deprecatedConfigurationPropertyAnnotation = deprecatedConfigurationPropertyAnnotation;
this.constructorBindingAnnotation = constructorBindingAnnotation;
this.autowiredAnnotation = autowiredAnnotation;
this.defaultValueAnnotation = defaultValueAnnotation;
this.endpointAnnotations = endpointAnnotations;
this.readOperationAnnotation = readOperationAnnotation;
this.nameAnnotation = nameAnnotation;
}
private static FieldValuesParser resolveFieldValuesParser(ProcessingEnvironment env) {
try {
return new JavaCompilerFieldValuesParser(env);
}
catch (Throwable ex) {
return FieldValuesParser.NONE;
}
}
TypeUtils getTypeUtils() {
return this.typeUtils;
}
Messager getMessager() {
return this.messager;
}
/**
* Return the default value of the field with the specified {@code name}.
* @param type the type to consider
* @param name the name of the field
* @return the default value or {@code null} if the field does not exist or no default
* value has been detected
*/
Object getFieldDefaultValue(TypeElement type, String name) {
return this.defaultValues.computeIfAbsent(type, this::resolveFieldValues).get(name);
}
boolean isExcluded(TypeMirror type) {
if (type == null) {
return false;
}
String typeName = type.toString();
if (typeName.endsWith("[]")) {
typeName = typeName.substring(0, typeName.length() - 2);
}
return TYPE_EXCLUDES.contains(typeName);
}
boolean isDeprecated(Element element) {
if (isElementDeprecated(element)) {
return true;
}
if (element instanceof VariableElement || element instanceof ExecutableElement) {
return isElementDeprecated(element.getEnclosingElement());
}
return false;
}
ItemDeprecation resolveItemDeprecation(Element element) {
AnnotationMirror annotation = getAnnotation(element, this.deprecatedConfigurationPropertyAnnotation);
String reason = null;
String replacement = null;
if (annotation != null) {
Map<String, Object> elementValues = getAnnotationElementValues(annotation);
reason = (String) elementValues.get("reason");
replacement = (String) elementValues.get("replacement");
}
reason = (reason == null || reason.isEmpty()) ? null : reason;
replacement = (replacement == null || replacement.isEmpty()) ? null : replacement;
return new ItemDeprecation(reason, replacement);
}
boolean hasConstructorBindingAnnotation(ExecutableElement element) {
return hasAnnotation(element, this.constructorBindingAnnotation);
}
boolean hasAutowiredAnnotation(ExecutableElement element) {
return hasAnnotation(element, this.autowiredAnnotation);
}
boolean hasAnnotation(Element element, String type) {
return getAnnotation(element, type) != null;
}
AnnotationMirror getAnnotation(Element element, String type) {
if (element != null) {
for (AnnotationMirror annotation : element.getAnnotationMirrors()) {
if (type.equals(annotation.getAnnotationType().toString())) {
return annotation;
}
}
}
return null;
}
/**
* Collect the annotations that are annotated or meta-annotated with the specified
* {@link TypeElement annotation}.
* @param element the element to inspect
* @param annotationType the annotation to discover
* @return the annotations that are annotated or meta-annotated with this annotation
*/
List<Element> getElementsAnnotatedOrMetaAnnotatedWith(Element element, TypeElement annotationType) {
LinkedList<Element> stack = new LinkedList<>();
stack.push(element);
collectElementsAnnotatedOrMetaAnnotatedWith(annotationType, stack);
stack.removeFirst();
return Collections.unmodifiableList(stack);
}
private boolean collectElementsAnnotatedOrMetaAnnotatedWith(TypeElement annotationType, LinkedList<Element> stack) {
Element element = stack.peekLast();
for (AnnotationMirror annotation : this.elements.getAllAnnotationMirrors(element)) {
Element annotationElement = annotation.getAnnotationType().asElement();
if (!stack.contains(annotationElement)) {
stack.addLast(annotationElement);
if (annotationElement.equals(annotationType)) {
return true;
}
if (!collectElementsAnnotatedOrMetaAnnotatedWith(annotationType, stack)) {
stack.removeLast();
}
}
}
return false;
}
Map<String, Object> getAnnotationElementValues(AnnotationMirror annotation) {
Map<String, Object> values = new LinkedHashMap<>();
annotation.getElementValues()
.forEach((name, value) -> values.put(name.getSimpleName().toString(), getAnnotationValue(value)));
return values;
}
private Object getAnnotationValue(AnnotationValue annotationValue) {
Object value = annotationValue.getValue();
if (value instanceof List) {
List<Object> values = new ArrayList<>();
((List<?>) value).forEach((v) -> values.add(((AnnotationValue) v).getValue()));
return values;
}
return value;
}
TypeElement getConfigurationPropertiesAnnotationElement() {
return this.elements.getTypeElement(this.configurationPropertiesAnnotation);
}
AnnotationMirror getConfigurationPropertiesAnnotation(Element element) {
return getAnnotation(element, this.configurationPropertiesAnnotation);
}
AnnotationMirror getNestedConfigurationPropertyAnnotation(Element element) {
return getAnnotation(element, this.nestedConfigurationPropertyAnnotation);
}
AnnotationMirror getDefaultValueAnnotation(Element element) {
return getAnnotation(element, this.defaultValueAnnotation);
}
Set<TypeElement> getEndpointAnnotationElements() {
return this.endpointAnnotations.stream().map(this.elements::getTypeElement).filter(Objects::nonNull)
.collect(Collectors.toSet());
}
AnnotationMirror getReadOperationAnnotation(Element element) {
return getAnnotation(element, this.readOperationAnnotation);
}
AnnotationMirror getNameAnnotation(Element element) {
return getAnnotation(element, this.nameAnnotation);
}
boolean hasNullableAnnotation(Element element) {
return getAnnotation(element, NULLABLE_ANNOTATION) != null;
}
private boolean isElementDeprecated(Element element) {
return hasAnnotation(element, "java.lang.Deprecated")
|| hasAnnotation(element, this.deprecatedConfigurationPropertyAnnotation);
}
private Map<String, Object> resolveFieldValues(TypeElement element) {
Map<String, Object> values = new LinkedHashMap<>();
resolveFieldValuesFor(values, element);
return values;
}
private void resolveFieldValuesFor(Map<String, Object> values, TypeElement element) {
try {
this.fieldValuesParser.getFieldValues(element).forEach((name, value) -> {
if (!values.containsKey(name)) {
values.put(name, value);
}
});
}
catch (Exception ex) {
// continue
}
Element superType = this.typeUtils.asElement(element.getSuperclass());
if (superType instanceof TypeElement && superType.asType().getKind() != TypeKind.NONE) {
resolveFieldValuesFor(values, (TypeElement) superType);
}
}
}
相关信息
相关文章
spring ConfigurationMetadataAnnotationProcessor 源码
spring ConstructorParameterPropertyDescriptor 源码
spring JavaBeanPropertyDescriptor 源码
spring LombokPropertyDescriptor 源码
0
赞
- 所属分类: 后端技术
- 本文标签: Spring Boot Java Spring
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
8、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦