@ -24,7 +24,6 @@ import java.lang.reflect.InvocationTargetException;
@@ -24,7 +24,6 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method ;
import java.lang.reflect.Modifier ;
import java.util.ArrayList ;
import java.util.Arrays ;
import java.util.Collection ;
import java.util.Collections ;
import java.util.LinkedHashSet ;
@ -79,6 +78,7 @@ import org.springframework.util.ReflectionUtils;
@@ -79,6 +78,7 @@ import org.springframework.util.ReflectionUtils;
* @author Juergen Hoeller
* @author Stephane Nicoll
* @author Phillip Webb
* @author Sam Brannen
* @since 2 . 5
* @see # setInitAnnotationType
* @see # setDestroyAnnotationType
@ -153,7 +153,7 @@ public class InitDestroyAnnotationBeanPostProcessor implements DestructionAwareB
@@ -153,7 +153,7 @@ public class InitDestroyAnnotationBeanPostProcessor implements DestructionAwareB
@Override
public void postProcessMergedBeanDefinition ( RootBeanDefinition beanDefinition , Class < ? > beanType , String beanName ) {
findInjection Metadata ( beanDefinition , beanType ) ;
findLifecycle Metadata ( beanDefinition , beanType ) ;
}
@Override
@ -161,7 +161,7 @@ public class InitDestroyAnnotationBeanPostProcessor implements DestructionAwareB
@@ -161,7 +161,7 @@ public class InitDestroyAnnotationBeanPostProcessor implements DestructionAwareB
public BeanRegistrationAotContribution processAheadOfTime ( RegisteredBean registeredBean ) {
RootBeanDefinition beanDefinition = registeredBean . getMergedBeanDefinition ( ) ;
beanDefinition . resolveDestroyMethodIfNecessary ( ) ;
LifecycleMetadata metadata = findInjection Metadata ( beanDefinition , registeredBean . getBeanClass ( ) ) ;
LifecycleMetadata metadata = findLifecycle Metadata ( beanDefinition , registeredBean . getBeanClass ( ) ) ;
if ( ! CollectionUtils . isEmpty ( metadata . initMethods ) ) {
String [ ] initMethodNames = safeMerge ( beanDefinition . getInitMethodNames ( ) , metadata . initMethods ) ;
beanDefinition . setInitMethodNames ( initMethodNames ) ;
@ -173,14 +173,14 @@ public class InitDestroyAnnotationBeanPostProcessor implements DestructionAwareB
@@ -173,14 +173,14 @@ public class InitDestroyAnnotationBeanPostProcessor implements DestructionAwareB
return null ;
}
private LifecycleMetadata findInjection Metadata ( RootBeanDefinition beanDefinition , Class < ? > beanType ) {
private LifecycleMetadata findLifecycle Metadata ( RootBeanDefinition beanDefinition , Class < ? > beanType ) {
LifecycleMetadata metadata = findLifecycleMetadata ( beanType ) ;
metadata . checkInitDestroyMethods ( beanDefinition ) ;
return metadata ;
}
private String [ ] safeMerge ( @Nullable String [ ] existingNames , Collection < LifecycleElement > detectedElement s ) {
Stream < String > detectedNames = detectedElement s . stream ( ) . map ( LifecycleElement : : getIdentifier ) ;
private static String [ ] safeMerge ( @Nullable String [ ] existingNames , Collection < LifecycleMethod > detectedMethod s ) {
Stream < String > detectedNames = detectedMethod s . stream ( ) . map ( LifecycleMethod : : getIdentifier ) ;
Stream < String > mergedNames = ( existingNames ! = null ?
Stream . concat ( Stream . of ( existingNames ) , detectedNames ) : detectedNames ) ;
return mergedNames . distinct ( ) . toArray ( String [ ] : : new ) ;
@ -217,12 +217,14 @@ public class InitDestroyAnnotationBeanPostProcessor implements DestructionAwareB
@@ -217,12 +217,14 @@ public class InitDestroyAnnotationBeanPostProcessor implements DestructionAwareB
if ( logger . isDebugEnabled ( ) ) {
logger . warn ( msg , ex . getTargetException ( ) ) ;
}
else {
else if ( logger . isWarnEnabled ( ) ) {
logger . warn ( msg + ": " + ex . getTargetException ( ) ) ;
}
}
catch ( Throwable ex ) {
logger . warn ( "Failed to invoke destroy method on bean with name '" + beanName + "'" , ex ) ;
if ( logger . isWarnEnabled ( ) ) {
logger . warn ( "Failed to invoke destroy method on bean with name '" + beanName + "'" , ex ) ;
}
}
}
@ -253,28 +255,27 @@ public class InitDestroyAnnotationBeanPostProcessor implements DestructionAwareB
@@ -253,28 +255,27 @@ public class InitDestroyAnnotationBeanPostProcessor implements DestructionAwareB
}
private LifecycleMetadata buildLifecycleMetadata ( final Class < ? > clazz ) {
if ( ! AnnotationUtils . isCandidateClass ( clazz , Arrays . asList ( this . initAnnotationType , this . destroyAnnotationType ) ) ) {
if ( ! AnnotationUtils . isCandidateClass ( clazz , List . of ( this . initAnnotationType , this . destroyAnnotationType ) ) ) {
return this . emptyLifecycleMetadata ;
}
List < LifecycleElement > initMethods = new ArrayList < > ( ) ;
List < LifecycleElement > destroyMethods = new ArrayList < > ( ) ;
List < LifecycleMethod > initMethods = new ArrayList < > ( ) ;
List < LifecycleMethod > destroyMethods = new ArrayList < > ( ) ;
Class < ? > targetClass = clazz ;
do {
final List < LifecycleElement > currInitMethods = new ArrayList < > ( ) ;
final List < LifecycleElement > currDestroyMethods = new ArrayList < > ( ) ;
final List < LifecycleMethod > currInitMethods = new ArrayList < > ( ) ;
final List < LifecycleMethod > currDestroyMethods = new ArrayList < > ( ) ;
ReflectionUtils . doWithLocalMethods ( targetClass , method - > {
if ( this . initAnnotationType ! = null & & method . isAnnotationPresent ( this . initAnnotationType ) ) {
LifecycleElement element = new LifecycleElement ( method ) ;
currInitMethods . add ( element ) ;
currInitMethods . add ( new LifecycleMethod ( method ) ) ;
if ( logger . isTraceEnabled ( ) ) {
logger . trace ( "Found init method on class [" + clazz . getName ( ) + "]: " + method ) ;
}
}
if ( this . destroyAnnotationType ! = null & & method . isAnnotationPresent ( this . destroyAnnotationType ) ) {
currDestroyMethods . add ( new LifecycleElement ( method ) ) ;
currDestroyMethods . add ( new LifecycleMethod ( method ) ) ;
if ( logger . isTraceEnabled ( ) ) {
logger . trace ( "Found destroy method on class [" + clazz . getName ( ) + "]: " + method ) ;
}
@ -312,18 +313,18 @@ public class InitDestroyAnnotationBeanPostProcessor implements DestructionAwareB
@@ -312,18 +313,18 @@ public class InitDestroyAnnotationBeanPostProcessor implements DestructionAwareB
private final Class < ? > targetClass ;
private final Collection < LifecycleElement > initMethods ;
private final Collection < LifecycleMethod > initMethods ;
private final Collection < LifecycleElement > destroyMethods ;
private final Collection < LifecycleMethod > destroyMethods ;
@Nullable
private volatile Set < LifecycleElement > checkedInitMethods ;
private volatile Set < LifecycleMethod > checkedInitMethods ;
@Nullable
private volatile Set < LifecycleElement > checkedDestroyMethods ;
private volatile Set < LifecycleMethod > checkedDestroyMethods ;
public LifecycleMetadata ( Class < ? > targetClass , Collection < LifecycleElement > initMethods ,
Collection < LifecycleElement > destroyMethods ) {
public LifecycleMetadata ( Class < ? > targetClass , Collection < LifecycleMethod > initMethods ,
Collection < LifecycleMethod > destroyMethods ) {
this . targetClass = targetClass ;
this . initMethods = initMethods ;
@ -331,23 +332,23 @@ public class InitDestroyAnnotationBeanPostProcessor implements DestructionAwareB
@@ -331,23 +332,23 @@ public class InitDestroyAnnotationBeanPostProcessor implements DestructionAwareB
}
public void checkInitDestroyMethods ( RootBeanDefinition beanDefinition ) {
Set < LifecycleElement > checkedInitMethods = new LinkedHashSet < > ( this . initMethods . size ( ) ) ;
for ( LifecycleElement element : this . initMethods ) {
String methodIdentifier = element . getIdentifier ( ) ;
Set < LifecycleMethod > checkedInitMethods = new LinkedHashSet < > ( this . initMethods . size ( ) ) ;
for ( LifecycleMethod lifecycleMethod : this . initMethods ) {
String methodIdentifier = lifecycleMethod . getIdentifier ( ) ;
if ( ! beanDefinition . isExternallyManagedInitMethod ( methodIdentifier ) ) {
beanDefinition . registerExternallyManagedInitMethod ( methodIdentifier ) ;
checkedInitMethods . add ( element ) ;
checkedInitMethods . add ( lifecycleMethod ) ;
if ( logger . isTraceEnabled ( ) ) {
logger . trace ( "Registered init method on class [" + this . targetClass . getName ( ) + "]: " + methodIdentifier ) ;
}
}
}
Set < LifecycleElement > checkedDestroyMethods = new LinkedHashSet < > ( this . destroyMethods . size ( ) ) ;
for ( LifecycleElement element : this . destroyMethods ) {
String methodIdentifier = element . getIdentifier ( ) ;
Set < LifecycleMethod > checkedDestroyMethods = new LinkedHashSet < > ( this . destroyMethods . size ( ) ) ;
for ( LifecycleMethod lifecycleMethod : this . destroyMethods ) {
String methodIdentifier = lifecycleMethod . getIdentifier ( ) ;
if ( ! beanDefinition . isExternallyManagedDestroyMethod ( methodIdentifier ) ) {
beanDefinition . registerExternallyManagedDestroyMethod ( methodIdentifier ) ;
checkedDestroyMethods . add ( element ) ;
checkedDestroyMethods . add ( lifecycleMethod ) ;
if ( logger . isTraceEnabled ( ) ) {
logger . trace ( "Registered destroy method on class [" + this . targetClass . getName ( ) + "]: " + methodIdentifier ) ;
}
@ -358,36 +359,36 @@ public class InitDestroyAnnotationBeanPostProcessor implements DestructionAwareB
@@ -358,36 +359,36 @@ public class InitDestroyAnnotationBeanPostProcessor implements DestructionAwareB
}
public void invokeInitMethods ( Object target , String beanName ) throws Throwable {
Collection < LifecycleElement > checkedInitMethods = this . checkedInitMethods ;
Collection < LifecycleElement > initMethodsToIterate =
Collection < LifecycleMethod > checkedInitMethods = this . checkedInitMethods ;
Collection < LifecycleMethod > initMethodsToIterate =
( checkedInitMethods ! = null ? checkedInitMethods : this . initMethods ) ;
if ( ! initMethodsToIterate . isEmpty ( ) ) {
for ( LifecycleElement element : initMethodsToIterate ) {
for ( LifecycleMethod lifecycleMethod : initMethodsToIterate ) {
if ( logger . isTraceEnabled ( ) ) {
logger . trace ( "Invoking init method on bean '" + beanName + "': " + element . getMethod ( ) ) ;
logger . trace ( "Invoking init method on bean '" + beanName + "': " + lifecycleMethod . getMethod ( ) ) ;
}
element . invoke ( target ) ;
lifecycleMethod . invoke ( target ) ;
}
}
}
public void invokeDestroyMethods ( Object target , String beanName ) throws Throwable {
Collection < LifecycleElement > checkedDestroyMethods = this . checkedDestroyMethods ;
Collection < LifecycleElement > destroyMethodsToUse =
Collection < LifecycleMethod > checkedDestroyMethods = this . checkedDestroyMethods ;
Collection < LifecycleMethod > destroyMethodsToUse =
( checkedDestroyMethods ! = null ? checkedDestroyMethods : this . destroyMethods ) ;
if ( ! destroyMethodsToUse . isEmpty ( ) ) {
for ( LifecycleElement element : destroyMethodsToUse ) {
for ( LifecycleMethod lifecycleMethod : destroyMethodsToUse ) {
if ( logger . isTraceEnabled ( ) ) {
logger . trace ( "Invoking destroy method on bean '" + beanName + "': " + element . getMethod ( ) ) ;
logger . trace ( "Invoking destroy method on bean '" + beanName + "': " + lifecycleMethod . getMethod ( ) ) ;
}
element . invoke ( target ) ;
lifecycleMethod . invoke ( target ) ;
}
}
}
public boolean hasDestroyMethods ( ) {
Collection < LifecycleElement > checkedDestroyMethods = this . checkedDestroyMethods ;
Collection < LifecycleElement > destroyMethodsToUse =
Collection < LifecycleMethod > checkedDestroyMethods = this . checkedDestroyMethods ;
Collection < LifecycleMethod > destroyMethodsToUse =
( checkedDestroyMethods ! = null ? checkedDestroyMethods : this . destroyMethods ) ;
return ! destroyMethodsToUse . isEmpty ( ) ;
}
@ -395,17 +396,17 @@ public class InitDestroyAnnotationBeanPostProcessor implements DestructionAwareB
@@ -395,17 +396,17 @@ public class InitDestroyAnnotationBeanPostProcessor implements DestructionAwareB
/ * *
* Class representing injection information about an annotated method .
* Class representing an annotated init or destroy method .
* /
private static class LifecycleElement {
private static class LifecycleMethod {
private final Method method ;
private final String identifier ;
public LifecycleElement ( Method method ) {
public LifecycleMethod ( Method method ) {
if ( method . getParameterCount ( ) ! = 0 ) {
throw new IllegalStateException ( "Lifecycle method annotation requires a no-arg method: " + method ) ;
throw new IllegalStateException ( "Lifecycle annotation requires a no-arg method: " + method ) ;
}
this . method = method ;
this . identifier = ( Modifier . isPrivate ( method . getModifiers ( ) ) ?
@ -422,18 +423,13 @@ public class InitDestroyAnnotationBeanPostProcessor implements DestructionAwareB
@@ -422,18 +423,13 @@ public class InitDestroyAnnotationBeanPostProcessor implements DestructionAwareB
public void invoke ( Object target ) throws Throwable {
ReflectionUtils . makeAccessible ( this . method ) ;
this . method . invoke ( target , ( Object [ ] ) null ) ;
this . method . invoke ( target ) ;
}
@Override
public boolean equals ( @Nullable Object other ) {
if ( this = = other ) {
return true ;
}
if ( ! ( other instanceof LifecycleElement otherElement ) ) {
return false ;
}
return ( this . identifier . equals ( otherElement . identifier ) ) ;
return ( this = = other | | ( other instanceof LifecycleMethod that & &
this . identifier . equals ( that . identifier ) ) ) ;
}
@Override