@ -20,8 +20,10 @@ import java.util.Arrays;
import java.util.Collection ;
import java.util.Collection ;
import java.util.Collections ;
import java.util.Collections ;
import java.util.HashSet ;
import java.util.HashSet ;
import java.util.LinkedHashMap ;
import java.util.LinkedHashSet ;
import java.util.LinkedHashSet ;
import java.util.List ;
import java.util.List ;
import java.util.Map ;
import java.util.Set ;
import java.util.Set ;
import org.springframework.beans.factory.BeanFactory ;
import org.springframework.beans.factory.BeanFactory ;
@ -38,6 +40,7 @@ import org.springframework.core.Ordered;
import org.springframework.core.env.Environment ;
import org.springframework.core.env.Environment ;
import org.springframework.core.io.support.SpringFactoriesLoader ;
import org.springframework.core.io.support.SpringFactoriesLoader ;
import org.springframework.core.type.AnnotationMetadata ;
import org.springframework.core.type.AnnotationMetadata ;
import org.springframework.util.CollectionUtils ;
import org.springframework.util.StringUtils ;
import org.springframework.util.StringUtils ;
/ * *
/ * *
@ -100,48 +103,49 @@ public class DatabaseInitializationDependencyConfigurer implements ImportBeanDef
@Override
@Override
public void postProcessBeanFactory ( ConfigurableListableBeanFactory beanFactory ) {
public void postProcessBeanFactory ( ConfigurableListableBeanFactory beanFactory ) {
Set< String > initializerBeanNames = detectInitializerBeanNames ( beanFactory ) ;
InitializerBeanNames initializerBeanNames = detectInitializerBeanNames ( beanFactory ) ;
if ( initializerBeanNames . isEmpty ( ) ) {
if ( initializerBeanNames . isEmpty ( ) ) {
return ;
return ;
}
}
String previousInitializerBeanName = null ;
Set < String > previousInitializerBeanNamesBatch = null ;
for ( String initializerBeanName : initializerBeanNames ) {
for ( Set < String > initializerBeanNamesBatch : initializerBeanNames . batchedBeanNames ( ) ) {
BeanDefinition beanDefinition = getBeanDefinition ( initializerBeanName , beanFactory ) ;
for ( String initializerBeanName : initializerBeanNamesBatch ) {
beanDefinition . setDependsOn ( merge ( beanDefinition . getDependsOn ( ) , previousInitializerBeanName ) ) ;
BeanDefinition beanDefinition = getBeanDefinition ( initializerBeanName , beanFactory ) ;
previousInitializerBeanName = initializerBeanName ;
beanDefinition
. setDependsOn ( merge ( beanDefinition . getDependsOn ( ) , previousInitializerBeanNamesBatch ) ) ;
}
previousInitializerBeanNamesBatch = initializerBeanNamesBatch ;
}
}
for ( String dependsOnInitializationBeanNames : detectDependsOnInitializationBeanNames ( beanFactory ) ) {
for ( String dependsOnInitializationBeanNames : detectDependsOnInitializationBeanNames ( beanFactory ) ) {
BeanDefinition beanDefinition = getBeanDefinition ( dependsOnInitializationBeanNames , beanFactory ) ;
BeanDefinition beanDefinition = getBeanDefinition ( dependsOnInitializationBeanNames , beanFactory ) ;
beanDefinition . setDependsOn ( merge ( beanDefinition . getDependsOn ( ) , initializerBeanNames )) ;
beanDefinition . setDependsOn ( merge ( beanDefinition . getDependsOn ( ) , initializerBeanNames .beanNames ( ) )) ;
}
}
}
}
private String [ ] merge ( String [ ] source , String additional ) {
return merge ( source , ( additional ! = null ) ? Collections . singleton ( additional ) : Collections . emptySet ( ) ) ;
}
private String [ ] merge ( String [ ] source , Set < String > additional ) {
private String [ ] merge ( String [ ] source , Set < String > additional ) {
if ( CollectionUtils . isEmpty ( additional ) ) {
return source ;
}
Set < String > result = new LinkedHashSet < > ( ( source ! = null ) ? Arrays . asList ( source ) : Collections . emptySet ( ) ) ;
Set < String > result = new LinkedHashSet < > ( ( source ! = null ) ? Arrays . asList ( source ) : Collections . emptySet ( ) ) ;
result . addAll ( additional ) ;
result . addAll ( additional ) ;
return StringUtils . toStringArray ( result ) ;
return StringUtils . toStringArray ( result ) ;
}
}
private Set< String > detectInitializerBeanNames ( ConfigurableListableBeanFactory beanFactory ) {
private InitializerBeanNames detectInitializerBeanNames ( ConfigurableListableBeanFactory beanFactory ) {
List < DatabaseInitializerDetector > detectors = getDetectors ( beanFactory , DatabaseInitializerDetector . class ) ;
List < DatabaseInitializerDetector > detectors = getDetectors ( beanFactory , DatabaseInitializerDetector . class ) ;
Set< String > beanNames = new LinkedHashSet < > ( ) ;
InitializerBeanNames initializerBeanNames = new InitializerBeanNames ( ) ;
for ( DatabaseInitializerDetector detector : detectors ) {
for ( DatabaseInitializerDetector detector : detectors ) {
for ( String beanName : detector . detect ( beanFactory ) ) {
for ( String beanName : detector . detect ( beanFactory ) ) {
BeanDefinition beanDefinition = beanFactory . getBeanDefinition ( beanName ) ;
BeanDefinition beanDefinition = beanFactory . getBeanDefinition ( beanName ) ;
beanDefinition . setAttribute ( DatabaseInitializerDetector . class . getName ( ) ,
beanDefinition . setAttribute ( DatabaseInitializerDetector . class . getName ( ) ,
detector . getClass ( ) . getName ( ) ) ;
detector . getClass ( ) . getName ( ) ) ;
beanNames. add ( beanName ) ;
initializerBeanNames. detected ( detector , beanName ) ;
}
}
}
}
beanNames = Collections . unmodifiableSet ( beanNames ) ;
for ( DatabaseInitializerDetector detector : detectors ) {
for ( DatabaseInitializerDetector detector : detectors ) {
detector . detectionComplete ( beanFactory , beanNames) ;
detector . detectionComplete ( beanFactory , initializerBeanNames. beanNames( ) ) ;
}
}
return b eanNames;
return initializerB eanNames;
}
}
private Collection < String > detectDependsOnInitializationBeanNames ( ConfigurableListableBeanFactory beanFactory ) {
private Collection < String > detectDependsOnInitializationBeanNames ( ConfigurableListableBeanFactory beanFactory ) {
@ -174,6 +178,31 @@ public class DatabaseInitializationDependencyConfigurer implements ImportBeanDef
}
}
}
}
static class InitializerBeanNames {
private final Map < DatabaseInitializerDetector , Set < String > > byDetectorBeanNames = new LinkedHashMap < > ( ) ;
private final Set < String > beanNames = new LinkedHashSet < > ( ) ;
private void detected ( DatabaseInitializerDetector detector , String beanName ) {
this . byDetectorBeanNames . computeIfAbsent ( detector , ( key ) - > new LinkedHashSet < > ( ) ) . add ( beanName ) ;
this . beanNames . add ( beanName ) ;
}
private boolean isEmpty ( ) {
return this . beanNames . isEmpty ( ) ;
}
private Iterable < Set < String > > batchedBeanNames ( ) {
return this . byDetectorBeanNames . values ( ) ;
}
private Set < String > beanNames ( ) {
return Collections . unmodifiableSet ( this . beanNames ) ;
}
}
}
}
}
}