org.springframework.beans
Class CachedIntrospectionResults

java.lang.Object
  extended by org.springframework.beans.CachedIntrospectionResults

public class CachedIntrospectionResults
extends java.lang.Object

Internal class that caches JavaBeans PropertyDescriptor information for a Java class. Not intended for direct use by application code.

Necessary for own caching of descriptors within the application's ClassLoader, rather than rely on the JDK's system-wide BeanInfo cache (in order to avoid leaks on ClassLoader shutdown).

Information is cached statically, so we don't need to create new objects of this class for every JavaBean we manipulate. Hence, this class implements the factory design pattern, using a private constructor and a static forClass(Class) factory method to obtain instances.

Since:
05 May 2001
Author:
Rod Johnson, Juergen Hoeller
See Also:
acceptClassLoader(ClassLoader), clearClassLoader(ClassLoader), forClass(Class)

Field Summary
(package private) static java.util.Set<java.lang.ClassLoader> acceptedClassLoaders
          Set of ClassLoaders that this CachedIntrospectionResults class will always accept classes from, even if the classes do not qualify as cache-safe.
private  java.beans.BeanInfo beanInfo
          The BeanInfo object for the introspected bean class
(package private) static java.util.Map<java.lang.Class,java.lang.Object> classCache
          Map keyed by class containing CachedIntrospectionResults.
private static Log logger
           
private  java.util.Map<java.lang.String,java.beans.PropertyDescriptor> propertyDescriptorCache
          PropertyDescriptor objects keyed by property name String
 
Constructor Summary
private CachedIntrospectionResults(java.lang.Class beanClass, boolean cacheFullMetadata)
          Create a new CachedIntrospectionResults instance for the given class.
 
Method Summary
static void acceptClassLoader(java.lang.ClassLoader classLoader)
          Accept the given ClassLoader as cache-safe, even if its classes would not qualify as cache-safe in this CachedIntrospectionResults class.
private  java.beans.PropertyDescriptor buildGenericTypeAwarePropertyDescriptor(java.lang.Class beanClass, java.beans.PropertyDescriptor pd)
           
static void clearClassLoader(java.lang.ClassLoader classLoader)
          Clear the introspection cache for the given ClassLoader, removing the introspection results for all classes underneath that ClassLoader, and deregistering the ClassLoader (and any of its children) from the acceptance list.
(package private) static CachedIntrospectionResults forClass(java.lang.Class beanClass)
          Create CachedIntrospectionResults for the given bean class.
(package private)  java.lang.Class getBeanClass()
           
(package private)  java.beans.BeanInfo getBeanInfo()
           
(package private)  java.beans.PropertyDescriptor getPropertyDescriptor(java.lang.String name)
           
(package private)  java.beans.PropertyDescriptor[] getPropertyDescriptors()
           
private static boolean isClassLoaderAccepted(java.lang.ClassLoader classLoader)
          Check whether this CachedIntrospectionResults class is configured to accept the given ClassLoader.
private static boolean isUnderneathClassLoader(java.lang.ClassLoader candidate, java.lang.ClassLoader parent)
          Check whether the given ClassLoader is underneath the given parent, that is, whether the parent is within the candidate's hierarchy.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

logger

private static final Log logger

acceptedClassLoaders

static final java.util.Set<java.lang.ClassLoader> acceptedClassLoaders
Set of ClassLoaders that this CachedIntrospectionResults class will always accept classes from, even if the classes do not qualify as cache-safe.


classCache

static final java.util.Map<java.lang.Class,java.lang.Object> classCache
Map keyed by class containing CachedIntrospectionResults. Needs to be a WeakHashMap with WeakReferences as values to allow for proper garbage collection in case of multiple class loaders.


beanInfo

private final java.beans.BeanInfo beanInfo
The BeanInfo object for the introspected bean class


propertyDescriptorCache

private final java.util.Map<java.lang.String,java.beans.PropertyDescriptor> propertyDescriptorCache
PropertyDescriptor objects keyed by property name String

Constructor Detail

CachedIntrospectionResults

private CachedIntrospectionResults(java.lang.Class beanClass,
                                   boolean cacheFullMetadata)
                            throws BeansException
Create a new CachedIntrospectionResults instance for the given class.

Parameters:
beanClass - the bean class to analyze
Throws:
BeansException - in case of introspection failure
Method Detail

acceptClassLoader

public static void acceptClassLoader(java.lang.ClassLoader classLoader)
Accept the given ClassLoader as cache-safe, even if its classes would not qualify as cache-safe in this CachedIntrospectionResults class.

This configuration method is only relevant in scenarios where the Spring classes reside in a 'common' ClassLoader (e.g. the system ClassLoader) whose lifecycle is not coupled to the application. In such a scenario, CachedIntrospectionResults would by default not cache any of the application's classes, since they would create a leak in the common ClassLoader.

Any acceptClassLoader call at application startup should be paired with a clearClassLoader(java.lang.ClassLoader) call at application shutdown.

Parameters:
classLoader - the ClassLoader to accept

clearClassLoader

public static void clearClassLoader(java.lang.ClassLoader classLoader)
Clear the introspection cache for the given ClassLoader, removing the introspection results for all classes underneath that ClassLoader, and deregistering the ClassLoader (and any of its children) from the acceptance list.

Parameters:
classLoader - the ClassLoader to clear the cache for

forClass

static CachedIntrospectionResults forClass(java.lang.Class beanClass)
                                    throws BeansException
Create CachedIntrospectionResults for the given bean class.

We don't want to use synchronization here. Object references are atomic, so we can live with doing the occasional unnecessary lookup at startup only.

Parameters:
beanClass - the bean class to analyze
Returns:
the corresponding CachedIntrospectionResults
Throws:
BeansException - in case of introspection failure

isClassLoaderAccepted

private static boolean isClassLoaderAccepted(java.lang.ClassLoader classLoader)
Check whether this CachedIntrospectionResults class is configured to accept the given ClassLoader.

Parameters:
classLoader - the ClassLoader to check
Returns:
whether the given ClassLoader is accepted
See Also:
acceptClassLoader(java.lang.ClassLoader)

isUnderneathClassLoader

private static boolean isUnderneathClassLoader(java.lang.ClassLoader candidate,
                                               java.lang.ClassLoader parent)
Check whether the given ClassLoader is underneath the given parent, that is, whether the parent is within the candidate's hierarchy.

Parameters:
candidate - the candidate ClassLoader to check
parent - the parent ClassLoader to check for

getBeanInfo

java.beans.BeanInfo getBeanInfo()

getBeanClass

java.lang.Class getBeanClass()

getPropertyDescriptor

java.beans.PropertyDescriptor getPropertyDescriptor(java.lang.String name)

getPropertyDescriptors

java.beans.PropertyDescriptor[] getPropertyDescriptors()

buildGenericTypeAwarePropertyDescriptor

private java.beans.PropertyDescriptor buildGenericTypeAwarePropertyDescriptor(java.lang.Class beanClass,
                                                                              java.beans.PropertyDescriptor pd)