помещение
В этой статье в основном анализируютсяIntrospector(Самоанализ, следует читать третий тон син,Я не нашел хорошего перевода, поэтому ниже назову его так.) Применение.Introspectorявляется специализированнымJavaBeanКласс инструмента, используемый для полученияJavaBeanописательные символы, обычно используемыеJavaBeanКлассы, связанные с дескриптором,BeanInfo,PropertyDescriptor,MethodDescriptor,BeanDescriptor,EventSetDescriptorа такжеParameterDescriptor. Далее будет медленно проанализировано, как используются эти классы, иIntrospectorнекоторые особенности.
Что такое JavaBean
JavaBeanЭто особый (на самом деле обычный, но не очень) класс, который в основном используется для передачи информации о данных.Методы этого класса в основном используются для доступа к приватным полям, а имена методов соответствуют определенным правилам именования ( поля все частные, каждое поле имеетSetterа такжеGetterМетоды, методы и поля именуются в соответствии с соглашением об именовании регистра верблюдов). Если вы передаете информацию между двумя модулями, вы можете инкапсулировать информацию вJavaBean, такой объект называется объектом-значением (Value Object)илиVO. Эта информация хранится в закрытых переменных класса черезSetter,Getterспособ получения.JavaBeanинформация вIntrospectorСоответствующее понятиеBeanInfo, который содержитJavaBeanвсеDescriptor(дескриптор), в основномPropertyDescriptor,MethodDescriptor(MethodDescriptorсодержитParameterDescriptor),BeanDescriptorа такжеEventSetDescriptor.
Разница между полем свойства и описанием свойства PropertiesDescriptor
если строгоJavaBean(Fieldимена не повторяются иFieldимеютSetterа такжеGetterметод), егоPropertyDescriptorбудет проанализированSetterа такжеGetterметод, объединить результаты синтаксического анализа и, наконец, получить соответствующийPropertyDescriptorпример. такPropertyDescriptorсодержит имена свойств и атрибутыSetterа такжеGetterметод (если он существует).
Разница между Интроспектором и Рефлексией
-
Reflection: Отражение — это получение всей информации о классе во время выполнения, вы можете получить всю определенную информацию о классе (включая переменные-члены, методы-члены, конструкторы и т. д.), вы можете манипулировать полями, методами, конструкторами и другими частями. класса. Его можно представить как зеркальное отражение или взгляд в зеркало.Такая операция имеет объективную окраску, то есть информация о классе, полученная при отражении, должна быть правильной. -
Introspector: Самоанализ реализуется на основе рефлексии, в основном используется для работыJavaBean, на основеJavaBeanспецификацияBeanРазбор информационных дескрипторов на основе классаSetterа такжеGetterметод для получения дескриптора класса. Можно представить себе как «саморефлексию», такие операции субъективны и не обязательно правильны (если свойство в классе неSetterа такжеGetterметод нельзя использоватьIntrospector).
Часто используемые классы, связанные с Introspector
В основном представляют методы, предоставляемые несколькими основными классами.
Introspector
Introspectorпохожий наBeanInfoКласс статической фабрики в основном предоставляет статические методы черезClassполучить экземплярBeanInfo,получатьBeanInfoПосле этого можно получить другие дескрипторы. Основной метод:
-
public static BeanInfo getBeanInfo(Class<?> beanClass):пройти черезClassполучить экземплярBeanInfoпример.
BeanInfo
BeanInfoэто интерфейс, конкретная реализацияGenericBeanInfo, через этот интерфейс можно получить различные типы дескрипторов класса. Основной метод:
-
BeanDescriptor getBeanDescriptor():ПолучатьJavaBeanДескриптор. -
EventSetDescriptor[] getEventSetDescriptors():ПолучатьJavaBeanиз всехEventSetDescriptor. -
PropertyDescriptor[] getPropertyDescriptors():ПолучатьJavaBeanиз всехPropertyDescriptor. -
MethodDescriptor[] getMethodDescriptors():ПолучатьJavaBeanиз всехMethodDescriptor.
Здесь следует отметить одну вещь.BeanInfo#getPropertyDescriptors()полученныйPropertyDescriptorмассив, кромеBeanПомимо свойств,также будет иметь атрибут с именемclassизPropertyDescriptorПример, его источникClassизgetClassметод, если вам не нужен этот атрибут, то лучше фильтровать после суждения.Этот момент необходимо иметь в виду, иначе могут возникнуть проблемы.
PropertyDescriptor
PropertyDescriptorпредставление классаJavaBeanкласс по памяти(Setterа такжеGetter) экспортирует атрибут, который должен быть наиболее распространенным классом в системе самоанализа. Основной метод:
-
synchronized Class<?> getPropertyType(): получить атрибутClassобъект. -
synchronized Method getReadMethod(): получено для чтения значений свойств (Getter) Методы; -
synchronized Method getWriteMethod(): получить значение свойства для записи (Setter) Методы. -
int hashCode(): получить хеш-значение объекта. -
synchronized void setReadMethod(Method readMethod): набор для чтения значений свойств (Getter) Методы. -
synchronized void setWriteMethod(Method writeMethod): набор для записи значений свойств (Setter) Методы.
Например:
public class Main {
public static void main(String[] args) throws Exception {
BeanInfo beanInfo = Introspector.getBeanInfo(Person.class);
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
if (!"class".equals(propertyDescriptor.getName())) {
System.out.println(propertyDescriptor.getName());
System.out.println(propertyDescriptor.getWriteMethod().getName());
System.out.println(propertyDescriptor.getReadMethod().getName());
System.out.println("=======================");
}
}
}
public static class Person {
private Long id;
private String name;
private Integer age;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
}
Выходной результат:
age
setAge
getAge
=======================
id
setId
getId
=======================
name
setName
getName
=======================
Неправильное использование Introspector может привести к переполнению памяти.
Если фреймворк или программа используетJavaBeans Introspector, то он эквивалентенКэш системного уровня включен, в этом кэше будут храниться ранее загруженные и проанализированныеJavabeanцитаты, когдаWebКогда сервер выключен, потому что этот кеш хранит этиJavabeanссылка, поэтому сборщик мусора не можетWebв контейнереJavaBeanОбъекты перерабатываются, в результате чего память становится все больше и больше. Еще один момент, который стоит отметить, ясноIntrospectorЕдинственный способ кеширования — очистить весь кеш-буфер, потому чтоJDKНевозможно определить, какие ссылки принадлежат текущему приложению, поэтому обновите всеIntrospectorКэш-буферы заставят все приложения на сервереIntrospectorКэш удален.Springпредоставлено вorg.springframework.web.util.IntrospectorCleanupListenerПросто для решения этой проблемыWebКогда сервер остановится, очистите этоIntrospectorкеш, сделай теJavabeanМожет быть правильно собран сборщиком мусора.
то естьJDKизIntrospectorУправление кешем ошибочно. Но если использовать вSpringВ системе нет этой проблемы, потому чтоSpringПучокIntrospectorУправление кэшем переданоSpringсебя вместоJDK(или вWebПосле уничтожения контейнера он полностью игнорируется), после того как все классы загружены и проанализированы,IntrospectorКэш очищается, чтобы избежать утечек памяти.Подробнее см.CachedIntrospectionResultsа такжеSpringBootМетоды обновления контекстаAbstractApplicationContext#refresh()серединаfinallyВ блоке кода есть метод очистки кешаAbstractApplicationContext#resetCommonCaches();. Но есть много программ и фреймворков, которые используютсяJavaBeans IntrospectorПосле этого нет никаких работ по очистке, таких какQuartz,StrutsИ так далее, такого рода операции станут скрытой опасностью утечки памяти.
резюме
- в стандарте
JavaBean, рассмотрите возможность использованияIntrospectorСистемный анализJavaBean, в основном, чтобы быстро получить его перед использованием отраженияJavaBeanизSetterа такжеGetterметод. - существует
Springсистемы, чтобы предотвратитьJDKКэш информации интроспекции не может быть утилизирован механизмом сборки мусора, что приводит к переполнению памяти.Основные операции можно настроить через конфигурацию.IntrospectorCleanupListenerПрофилактика, есть и другой способ, черезCachedIntrospectionResultsКлассное самоуправлениеIntrospectorкэш (это элегантный способ избежать сброса всегоIntrospectorкэш-буферы и заставить другие приложенияIntrospectorтакже пустует)То есть кеш, связанный с Introspector, которым управляет сам JDK, передается Spring для управления собой.. существуетSpringBootМетоды обновления контекстаAbstractApplicationContext#refresh()серединаfinallyВ блоке кода есть метод очистки кешаAbstractApplicationContext#resetCommonCaches();, который называетсяCachedIntrospectionResults#clearClassLoader(getClassLoader())Метод заключается в очистке указанногоClassLoaderвсе подIntrospectorСсылка на кеш в .
(Конец этой статьи e-a-20200811 c-1-d)
Это оригинальная статья, опубликованная в паблике «Throwable», которая включена в альбом «Java Basics and Advanced».