AnnotationJmxAttributeSource uses MergedAnnotation API directly
Includes deprecation of AnnotationBeanUtils class (now unused). Closes gh-22657
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -17,19 +17,30 @@
|
||||
package org.springframework.jmx.export.annotation;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.annotation.AnnotationBeanUtils;
|
||||
import org.springframework.beans.BeanWrapper;
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.beans.PropertyAccessorFactory;
|
||||
import org.springframework.beans.PropertyValue;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.beans.factory.config.EmbeddedValueResolver;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.annotation.AnnotationFilter;
|
||||
import org.springframework.core.annotation.MergedAnnotation;
|
||||
import org.springframework.core.annotation.MergedAnnotationPredicates;
|
||||
import org.springframework.core.annotation.MergedAnnotations;
|
||||
import org.springframework.core.annotation.MergedAnnotations.SearchStrategy;
|
||||
import org.springframework.core.annotation.RepeatableContainers;
|
||||
import org.springframework.jmx.export.metadata.InvalidMetadataException;
|
||||
import org.springframework.jmx.export.metadata.JmxAttributeSource;
|
||||
import org.springframework.lang.Nullable;
|
||||
@@ -65,46 +76,69 @@ public class AnnotationJmxAttributeSource implements JmxAttributeSource, BeanFac
|
||||
@Override
|
||||
@Nullable
|
||||
public org.springframework.jmx.export.metadata.ManagedResource getManagedResource(Class<?> beanClass) throws InvalidMetadataException {
|
||||
ManagedResource ann = AnnotationUtils.findAnnotation(beanClass, ManagedResource.class);
|
||||
if (ann == null) {
|
||||
MergedAnnotation<ManagedResource> ann = MergedAnnotations.from(beanClass, SearchStrategy.EXHAUSTIVE)
|
||||
.get(ManagedResource.class).withNonMergedAttributes();
|
||||
if (!ann.isPresent()) {
|
||||
return null;
|
||||
}
|
||||
Class<?> declaringClass = AnnotationUtils.findAnnotationDeclaringClass(ManagedResource.class, beanClass);
|
||||
Class<?> declaringClass = (Class<?>) ann.getSource();
|
||||
Class<?> target = (declaringClass != null && !declaringClass.isInterface() ? declaringClass : beanClass);
|
||||
if (!Modifier.isPublic(target.getModifiers())) {
|
||||
throw new InvalidMetadataException("@ManagedResource class '" + target.getName() + "' must be public");
|
||||
}
|
||||
org.springframework.jmx.export.metadata.ManagedResource managedResource = new org.springframework.jmx.export.metadata.ManagedResource();
|
||||
AnnotationBeanUtils.copyPropertiesToBean(ann, managedResource, this.embeddedValueResolver);
|
||||
return managedResource;
|
||||
|
||||
org.springframework.jmx.export.metadata.ManagedResource bean = new org.springframework.jmx.export.metadata.ManagedResource();
|
||||
Map<String, Object> map = ann.asMap();
|
||||
List<PropertyValue> list = new ArrayList<>(map.size());
|
||||
map.forEach((attrName, attrValue) -> {
|
||||
if (!"value".equals(attrName)) {
|
||||
Object value = attrValue;
|
||||
if (this.embeddedValueResolver != null && value instanceof String) {
|
||||
value = this.embeddedValueResolver.resolveStringValue((String) value);
|
||||
}
|
||||
list.add(new PropertyValue(attrName, value));
|
||||
}
|
||||
});
|
||||
PropertyAccessorFactory.forBeanPropertyAccess(bean).setPropertyValues(new MutablePropertyValues(list));
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public org.springframework.jmx.export.metadata.ManagedAttribute getManagedAttribute(Method method) throws InvalidMetadataException {
|
||||
ManagedAttribute ann = AnnotationUtils.findAnnotation(method, ManagedAttribute.class);
|
||||
if (ann == null) {
|
||||
MergedAnnotation<ManagedAttribute> ann = MergedAnnotations.from(method, SearchStrategy.EXHAUSTIVE)
|
||||
.get(ManagedAttribute.class).withNonMergedAttributes();
|
||||
if (!ann.isPresent()) {
|
||||
return null;
|
||||
}
|
||||
org.springframework.jmx.export.metadata.ManagedAttribute managedAttribute = new org.springframework.jmx.export.metadata.ManagedAttribute();
|
||||
AnnotationBeanUtils.copyPropertiesToBean(ann, managedAttribute, "defaultValue");
|
||||
if (ann.defaultValue().length() > 0) {
|
||||
managedAttribute.setDefaultValue(ann.defaultValue());
|
||||
|
||||
org.springframework.jmx.export.metadata.ManagedAttribute bean = new org.springframework.jmx.export.metadata.ManagedAttribute();
|
||||
Map<String, Object> map = ann.asMap();
|
||||
MutablePropertyValues pvs = new MutablePropertyValues(map);
|
||||
pvs.removePropertyValue("defaultValue");
|
||||
PropertyAccessorFactory.forBeanPropertyAccess(bean).setPropertyValues(pvs);
|
||||
String defaultValue = (String) map.get("defaultValue");
|
||||
if (defaultValue.length() > 0) {
|
||||
bean.setDefaultValue(defaultValue);
|
||||
}
|
||||
return managedAttribute;
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public org.springframework.jmx.export.metadata.ManagedMetric getManagedMetric(Method method) throws InvalidMetadataException {
|
||||
ManagedMetric ann = AnnotationUtils.findAnnotation(method, ManagedMetric.class);
|
||||
MergedAnnotation<ManagedMetric> ann = MergedAnnotations.from(method, SearchStrategy.EXHAUSTIVE)
|
||||
.get(ManagedMetric.class).withNonMergedAttributes();
|
||||
|
||||
return copyPropertiesToBean(ann, org.springframework.jmx.export.metadata.ManagedMetric.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public org.springframework.jmx.export.metadata.ManagedOperation getManagedOperation(Method method) throws InvalidMetadataException {
|
||||
ManagedOperation ann = AnnotationUtils.findAnnotation(method, ManagedOperation.class);
|
||||
MergedAnnotation<ManagedOperation> ann = MergedAnnotations.from(method, SearchStrategy.EXHAUSTIVE)
|
||||
.get(ManagedOperation.class).withNonMergedAttributes();
|
||||
|
||||
return copyPropertiesToBean(ann, org.springframework.jmx.export.metadata.ManagedOperation.class);
|
||||
}
|
||||
|
||||
@@ -112,8 +146,9 @@ public class AnnotationJmxAttributeSource implements JmxAttributeSource, BeanFac
|
||||
public org.springframework.jmx.export.metadata.ManagedOperationParameter[] getManagedOperationParameters(Method method)
|
||||
throws InvalidMetadataException {
|
||||
|
||||
Set<ManagedOperationParameter> anns = AnnotationUtils.getRepeatableAnnotations(
|
||||
List<MergedAnnotation<? extends Annotation>> anns = getRepeatableAnnotations(
|
||||
method, ManagedOperationParameter.class, ManagedOperationParameters.class);
|
||||
|
||||
return copyPropertiesToBeanArray(anns, org.springframework.jmx.export.metadata.ManagedOperationParameter.class);
|
||||
}
|
||||
|
||||
@@ -121,29 +156,45 @@ public class AnnotationJmxAttributeSource implements JmxAttributeSource, BeanFac
|
||||
public org.springframework.jmx.export.metadata.ManagedNotification[] getManagedNotifications(Class<?> clazz)
|
||||
throws InvalidMetadataException {
|
||||
|
||||
Set<ManagedNotification> anns = AnnotationUtils.getRepeatableAnnotations(
|
||||
List<MergedAnnotation<? extends Annotation>> anns = getRepeatableAnnotations(
|
||||
clazz, ManagedNotification.class, ManagedNotifications.class);
|
||||
|
||||
return copyPropertiesToBeanArray(anns, org.springframework.jmx.export.metadata.ManagedNotification.class);
|
||||
}
|
||||
|
||||
|
||||
private static List<MergedAnnotation<? extends Annotation>> getRepeatableAnnotations(
|
||||
AnnotatedElement annotatedElement, Class<? extends Annotation> annotationType,
|
||||
Class<? extends Annotation> containerAnnotationType) {
|
||||
|
||||
return MergedAnnotations.from(annotatedElement, SearchStrategy.EXHAUSTIVE,
|
||||
RepeatableContainers.of(annotationType, containerAnnotationType), AnnotationFilter.PLAIN)
|
||||
.stream(annotationType)
|
||||
.filter(MergedAnnotationPredicates.firstRunOf(MergedAnnotation::getAggregateIndex))
|
||||
.map(MergedAnnotation::withNonMergedAttributes)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T> T[] copyPropertiesToBeanArray(Collection<? extends Annotation> anns, Class<T> beanClass) {
|
||||
private static <T> T[] copyPropertiesToBeanArray(
|
||||
List<MergedAnnotation<? extends Annotation>> anns, Class<T> beanClass) {
|
||||
|
||||
T[] beans = (T[]) Array.newInstance(beanClass, anns.size());
|
||||
int i = 0;
|
||||
for (Annotation ann : anns) {
|
||||
for (MergedAnnotation<? extends Annotation> ann : anns) {
|
||||
beans[i++] = copyPropertiesToBean(ann, beanClass);
|
||||
}
|
||||
return beans;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static <T> T copyPropertiesToBean(@Nullable Annotation ann, Class<T> beanClass) {
|
||||
if (ann == null) {
|
||||
private static <T> T copyPropertiesToBean(MergedAnnotation<? extends Annotation> ann, Class<T> beanClass) {
|
||||
if (!ann.isPresent()) {
|
||||
return null;
|
||||
}
|
||||
T bean = BeanUtils.instantiateClass(beanClass);
|
||||
AnnotationBeanUtils.copyPropertiesToBean(ann, bean);
|
||||
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(bean);
|
||||
bw.setPropertyValues(new MutablePropertyValues(ann.asMap()));
|
||||
return bean;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user