This article mainly analyzes the usage of Introspector
. Introspector
is a tool class that deals specifically with JavaBean
and is used to get the descriptors in JavaBean
. The commonly used descriptor-related classes of JavaBean
are BeanInfo
, PropertyDescriptor
, MethodDescriptor
, BeanDescriptor
, EventSetDescriptor
and ParameterDescriptor
. The following will slowly analyze how these classes are used, as well as some of the features of Introspector
.
What is JavaBean
JavaBean
is a special (actually, it’s okay to say ordinary, it’s not very special) class, mainly used to pass data information, the methods in this class are mainly used to access private fields, and the method names conform to some naming rules (fields are private, each field has Setter
and Getter
methods, methods and fields named to meet the first letter lower case hump naming ). If information is passed between two modules, it can be encapsulated in a JavaBean
, which is called a Value Object or VO. This information is stored in private variables of the class and is obtained through the Setter
, Getter
methods. The information of JavaBean
corresponds to the concept of BeanInfo
in Introspector
, which contains all the Descriptor
of JavaBean
, mainly PropertyDescriptor
, MethodDescriptor
(MethodDescriptor
contains ParameterDescriptor
), BeanDescriptor
and EventSetDescriptor
.
The difference between Field
and PropertiesDescriptor
If it is a strict JavaBean
(the Field
name is not repeated and the Field
has Setter
and Getter
methods), its PropertyDescriptor
will merge the results by parsing the Setter
and Getter
methods and finally get the corresponding PropertyDescriptor
instance. So PropertyDescriptor
contains the property name and the property’s Setter
and Getter
methods (if they exist).
The difference between Introspector
and Reflection
Reflection
: Reflection is the process of getting all the information about a class at runtime. You can get all the defined information about the class (including member variables, member methods, constructors, etc.) You can manipulate the fields, methods, constructors, and other parts of the class. It can be imagined as mirror reflection or looking in the mirror, such operation is with an objective color, that is, the reflection to obtain the class information is necessarily correct.Introspector
: introspection based on reflection, mainly used to operateJavaBean
, based on the specification ofJavaBean
toBean
information descriptor resolution, based on the classSetter
andGetter
methods, you can get to the class descriptor. It can be imagined as “self-reflection”, which is subjective and not necessarily correct (if a class does not haveSetter
andGetter
methods for its properties, introspection cannot be used).
Commonly used introspection-related classes
It mainly introduces the methods provided by several core classes.
Introspector
Introspector
is similar to the static factory class of BeanInfo
, which mainly provides static methods to get BeanInfo
through Class
instances, and after getting BeanInfo
, you will be able to get other descriptors. Main methods:
public static BeanInfo getBeanInfo(Class<? > beanClass)
: Get theBeanInfo
instance from theClass
instance.
BeanInfo
BeanInfo
is an interface, the concrete implementation of which is GenericBeanInfo
, through which you can get the descriptors of various types of a class. Main methods:
BeanDescriptor getBeanDescriptor()
: get JavaBean descriptors.EventSetDescriptor[] getEventSetDescriptors()
: Get all the EventSetDescriptors of the JavaBean.PropertyDescriptor[] getPropertyDescriptors()
: Get all the PropertyDescriptors of the JavaBean.MethodDescriptor[] getMethodDescriptors()
: Get all the MethodDescriptors of the JavaBean.
Note that the PropertyDescriptor
array obtained through BeanInfo#getPropertyDescriptors()
will have an instance of PropertyDescriptor
named class
in addition to the Bean
property, and its source is the getClass
method of Class
.
If this property is not needed then it is better to filter it after judging.
PropertyDescriptor
The PropertyDescriptor
class represents the JavaBean
class that exports a property through the memory (Setter
and Getter
) and it should be the most common class in the introspection system. Main methods.
synchronized Class<? > getPropertyType()
: Get the Class object of the property.synchronized Method getReadMethod()
: gets the method used to read the value of the property.synchronized Method getWriteMethod()
: get the method used to write the value of the property.int hashCode()
: get the hash value of the object.synchronized void setReadMethod(Method readMethod)
: set the method used to read the value of the property (Getter).synchronized void setWriteMethod(Method writeMethod)
: sets the method used to write the value of the property (Setter
).
As an example:
|
|
Output results:
Improper use of Introspector can lead to memory overflows
If the framework or program uses JavaBeans Introspector
, then it is equivalent to enabling a system-level cache, which holds references to some Javabean
s that have been loaded and analyzed, and when the web
server is closed, because this cache holds references to these Javabean
s, the garbage collector cannot recycle the JavaBean
objects in the Web
container, resulting in an increasing amount of memory. It is also worth noting that the only way to clear the Introspector
cache is to flush the entire cache buffer. This is because the JDK
cannot determine which references belong to the current application, so flushing the entire Introspector
cache buffer will result in deleting the Introspector
cache for all applications on the server. The org.springframework.web.util.IntrospectorCleanupListener
provided in Spring
is designed to solve this problem by cleaning up this Introspector
cache when the Web
server stops, so that those Javabean
can be properly recycled by the garbage collector.
That is, the Introspector
cache management of the JDK
is somewhat flawed. But this is not a problem if used in the Spring
system, because Spring
transfers the management of the Introspector
cache to Spring
itself and not to JDK
(or to the Web
container after it is destroyed), and after loading and analyzing all classes, it cleans up the Introspector
cache against the class loader. Introspector
cache cleanup to avoid memory leaks, see CachedIntrospectionResults
and SpringBoot
refresh context method AbstractApplicationContext#refresh()
for details. finally
block of code exists to clear the cache method AbstractApplicationContext#resetCommonCaches();
. But there are many programs and frameworks that do not clean up after using JavaBeans Introspector
, such as Quartz
, Struts
, etc. This type of operation can become a potential memory leak.
Summary
- In the standard
JavaBean
, you can consider using theIntrospector
system to parse theJavaBean
, mainly to facilitate the use of reflection before the time to quickly get to theSetter
andGetter
methods of the JavaBean. - In the
Spring
system, in order to prevent the JDK’s cache of introspection information from being recovered by the garbage collection mechanism and causing memory overflow, the main operation can be prevented by configuring theIntrospectorCleanupListener
, but there is another way, which is through theCachedIntrospectionResults
class self-managedIntrospector
cache (this way is the elegant way, so as to avoid refreshing the entireIntrospector
cache buffer and cause other applicationsIntrospector
is also emptied), that is, theJdk
self-managedIntrospector
-related cache to Spring itself. The methodAbstractApplicationContext#refresh()
in thefinally
block of theSpringBoot
refresh context has the methodAbstractApplicationContext#resetCommonCaches();
, which calls theCachedIntrospectionResults#clearClassLoader(getClassLoader()
method to clear all the references to the cache in theIntrospector
under the specifiedClassLoader
.
Reference https://www.throwx.cn/2019/12/25/java-introspector-usage/