Browse Source

Introduce DeferredBeanRegistrar and BeanRegistry#containsBean methods

Closes gh-21497
pull/36559/head
Juergen Hoeller 2 days ago
parent
commit
7502b92392
  1. 23
      spring-beans/src/main/java/org/springframework/beans/factory/BeanRegistry.java
  2. 32
      spring-beans/src/main/java/org/springframework/beans/factory/support/BeanRegistryAdapter.java
  3. 46
      spring-context/src/main/java/org/springframework/context/DeferredBeanRegistrar.java
  4. 17
      spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java
  5. 25
      spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java
  6. 12
      spring-context/src/main/java/org/springframework/context/annotation/Import.java
  7. 49
      spring-context/src/main/java/org/springframework/context/support/GenericApplicationContext.java
  8. 41
      spring-context/src/test/java/org/springframework/context/annotation/beanregistrar/BeanRegistrarConfigurationTests.java
  9. 40
      spring-context/src/test/java/org/springframework/context/support/GenericApplicationContextTests.java
  10. 37
      spring-context/src/testFixtures/java/org/springframework/context/testfixture/beans/factory/MyDeferredBeanRegistrar.java
  11. 36
      spring-context/src/testFixtures/java/org/springframework/context/testfixture/beans/factory/MyRegularBeanRegistrar.java
  12. 26
      spring-context/src/testFixtures/java/org/springframework/context/testfixture/context/annotation/registrar/MyDeferredBeanRegistrarConfiguration.java
  13. 26
      spring-context/src/testFixtures/java/org/springframework/context/testfixture/context/annotation/registrar/MyRegularBeanRegistrarConfiguration.java
  14. 31
      spring-context/src/testFixtures/java/org/springframework/context/testfixture/context/annotation/registrar/TestBeanConfiguration.java

23
spring-beans/src/main/java/org/springframework/beans/factory/BeanRegistry.java

@ -33,6 +33,7 @@ import org.springframework.core.env.Environment; @@ -33,6 +33,7 @@ import org.springframework.core.env.Environment;
* programmatic bean registration capabilities.
*
* @author Sebastien Deleuze
* @author Juergen Hoeller
* @since 7.0
*/
public interface BeanRegistry {
@ -140,6 +141,28 @@ public interface BeanRegistry { @@ -140,6 +141,28 @@ public interface BeanRegistry {
*/
<T> void registerBean(String name, ParameterizedTypeReference<T> beanType, Consumer<Spec<T>> customizer);
/**
* Determine whether a bean of the given name is already registered.
* @param name the name of the bean
* @since 7.1
*/
boolean containsBean(String name);
/**
* Determine whether a bean of the given type is already registered.
* @param beanType the type of the bean
* @since 7.1
*/
boolean containsBean(Class<?> beanType);
/**
* Determine whether a bean of the given generics-containing type is
* already registered.
* @param beanType the generics-containing type of the bean
* @since 7.1
*/
<T> boolean containsBean(ParameterizedTypeReference<T> beanType);
/**
* Specification for customizing a bean.

32
spring-beans/src/main/java/org/springframework/beans/factory/support/BeanRegistryAdapter.java

@ -25,6 +25,8 @@ import org.jspecify.annotations.Nullable; @@ -25,6 +25,8 @@ import org.jspecify.annotations.Nullable;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.BeanRegistrar;
import org.springframework.beans.factory.BeanRegistry;
import org.springframework.beans.factory.ListableBeanFactory;
@ -81,6 +83,12 @@ public class BeanRegistryAdapter implements BeanRegistry { @@ -81,6 +83,12 @@ public class BeanRegistryAdapter implements BeanRegistry {
}
@Override
public void register(BeanRegistrar registrar) {
Assert.notNull(registrar, "BeanRegistrar must not be null");
registrar.register(this, this.environment);
}
@Override
public void registerAlias(String name, String alias) {
this.beanRegistry.registerAlias(name, alias);
@ -170,9 +178,19 @@ public class BeanRegistryAdapter implements BeanRegistry { @@ -170,9 +178,19 @@ public class BeanRegistryAdapter implements BeanRegistry {
}
@Override
public void register(BeanRegistrar registrar) {
Assert.notNull(registrar, "'registrar' must not be null");
registrar.register(this, this.environment);
public boolean containsBean(String name) {
return this.beanFactory.containsBean(name);
}
@Override
public boolean containsBean(Class<?> beanType) {
return BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, beanType).length > 0;
}
@Override
public <T> boolean containsBean(ParameterizedTypeReference<T> beanType) {
ResolvableType resolvableType = ResolvableType.forType(beanType);
return BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, resolvableType).length > 0;
}
@ -218,9 +236,9 @@ public class BeanRegistryAdapter implements BeanRegistry { @@ -218,9 +236,9 @@ public class BeanRegistryAdapter implements BeanRegistry {
private final RootBeanDefinition beanDefinition;
private final ListableBeanFactory beanFactory;
private final BeanFactory beanFactory;
public BeanSpecAdapter(RootBeanDefinition beanDefinition, ListableBeanFactory beanFactory) {
public BeanSpecAdapter(RootBeanDefinition beanDefinition, BeanFactory beanFactory) {
this.beanDefinition = beanDefinition;
this.beanFactory = beanFactory;
}
@ -296,9 +314,9 @@ public class BeanRegistryAdapter implements BeanRegistry { @@ -296,9 +314,9 @@ public class BeanRegistryAdapter implements BeanRegistry {
private static class SupplierContextAdapter implements SupplierContext {
private final ListableBeanFactory beanFactory;
private final BeanFactory beanFactory;
public SupplierContextAdapter(ListableBeanFactory beanFactory) {
public SupplierContextAdapter(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}

46
spring-context/src/main/java/org/springframework/context/DeferredBeanRegistrar.java

@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
/*
* Copyright 2002-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context;
import org.springframework.beans.factory.BeanRegistrar;
import org.springframework.beans.factory.BeanRegistry;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.env.Environment;
/**
* A variant of {@link BeanRegistrar} which aims to be invoked
* at the end of the bean registration phase, coming after regular
* bean definition reading and configuration class processing.
*
* <p>This allows for seeing all user-registered beans, potentially
* reacting to their presence. The {@code containsBean} methods on
* {@link BeanRegistry} will provide reliable answers, independent
* of the order of user bean registration versus {@code BeanRegistrar}
* import/registration.
*
* @author Juergen Hoeller
* @since 7.1
* @see #register(BeanRegistry, Environment)
* @see BeanRegistry#containsBean(String)
* @see BeanRegistry#containsBean(Class)
* @see BeanRegistry#containsBean(ParameterizedTypeReference)
* @see org.springframework.context.support.GenericApplicationContext#register( BeanRegistrar...)
* @see org.springframework.context.annotation.Import
*/
public interface DeferredBeanRegistrar extends BeanRegistrar {
}

17
spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java

@ -45,6 +45,7 @@ import org.springframework.beans.factory.support.BeanNameGenerator; @@ -45,6 +45,7 @@ import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.beans.factory.support.BeanRegistryAdapter;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.DeferredBeanRegistrar;
import org.springframework.context.annotation.ConfigurationCondition.ConfigurationPhase;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.env.Environment;
@ -423,12 +424,16 @@ class ConfigurationClassBeanDefinitionReader { @@ -423,12 +424,16 @@ class ConfigurationClassBeanDefinitionReader {
}
private void loadBeanDefinitionsFromBeanRegistrars(MultiValueMap<String, BeanRegistrar> registrars) {
if (!(this.registry instanceof ListableBeanFactory beanFactory)) {
throw new IllegalStateException("Cannot support bean registrars since " +
this.registry.getClass().getName() + " does not implement ListableBeanFactory");
}
registrars.values().forEach(registrarList -> registrarList.forEach(registrar -> registrar.register(new BeanRegistryAdapter(
this.registry, beanFactory, this.environment, registrar.getClass()), this.environment)));
registrars.values().forEach(registrarList -> registrarList.forEach(registrar -> {
if (!(registrar instanceof DeferredBeanRegistrar)) {
if (!(this.registry instanceof ListableBeanFactory beanFactory)) {
throw new IllegalStateException("Cannot support bean registrars since " +
this.registry.getClass().getName() + " does not implement ListableBeanFactory");
}
registrar.register(new BeanRegistryAdapter(
this.registry, beanFactory, this.environment, registrar.getClass()), this.environment);
}
}));
}

25
spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java

@ -94,11 +94,13 @@ import org.springframework.beans.factory.support.RegisteredBean; @@ -94,11 +94,13 @@ import org.springframework.beans.factory.support.RegisteredBean;
import org.springframework.beans.factory.support.RegisteredBean.InstantiationDescriptor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.ApplicationStartupAware;
import org.springframework.context.DeferredBeanRegistrar;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.ConfigurationClassEnhancer.EnhancedConfiguration;
import org.springframework.core.Ordered;
import org.springframework.core.PriorityOrdered;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.StandardEnvironment;
@ -208,7 +210,7 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo @@ -208,7 +210,7 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE; // within PriorityOrdered
return Ordered.LOWEST_PRECEDENCE - 1; // within PriorityOrdered, 1 before DeferredRegistryPostProcessor
}
/**
@ -222,7 +224,7 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo @@ -222,7 +224,7 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
/**
* Set the {@link ProblemReporter} to use.
* <p>Used to register any problems detected with {@link Configuration} or {@link Bean}
* declarations. For instance, an @Bean method marked as {@code final} is illegal
* declarations. For instance, a @Bean method marked as {@code final} is illegal
* and would be reported as a problem. Defaults to {@link FailFastProblemReporter}.
*/
public void setProblemReporter(@Nullable ProblemReporter problemReporter) {
@ -490,6 +492,25 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo @@ -490,6 +492,25 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
}
while (!candidates.isEmpty());
// Process DeferredBeanRegistrars, if any.
List<DeferredBeanRegistrar> deferredBeanRegistrars = new ArrayList<>();
for (List<BeanRegistrar> registrars : this.beanRegistrars.values()) {
for (BeanRegistrar registrar : registrars) {
if (registrar instanceof DeferredBeanRegistrar deferredRegistrar) {
deferredBeanRegistrars.add(deferredRegistrar);
}
}
}
AnnotationAwareOrderComparator.sort(deferredBeanRegistrars);
for (DeferredBeanRegistrar registrar : deferredBeanRegistrars) {
if (!(registry instanceof ListableBeanFactory beanFactory)) {
throw new IllegalStateException("Cannot support bean registrars since " +
registry.getClass().getName() + " does not implement ListableBeanFactory");
}
registrar.register(new BeanRegistryAdapter(
registry, beanFactory, this.environment, registrar.getClass()), this.environment);
}
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
if (singletonRegistry != null && !singletonRegistry.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
singletonRegistry.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());

12
spring-context/src/main/java/org/springframework/context/annotation/Import.java

@ -23,6 +23,7 @@ import java.lang.annotation.RetentionPolicy; @@ -23,6 +23,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.beans.factory.BeanRegistrar;
import org.springframework.context.DeferredBeanRegistrar;
/**
* Indicates one or more <em>component classes</em> to import &mdash; typically
@ -31,9 +32,9 @@ import org.springframework.beans.factory.BeanRegistrar; @@ -31,9 +32,9 @@ import org.springframework.beans.factory.BeanRegistrar;
* <p>Provides functionality equivalent to the {@code <import/>} element in Spring XML.
*
* <p>Allows for importing {@code @Configuration} classes, {@link ImportSelector},
* {@link ImportBeanDefinitionRegistrar}, and {@link BeanRegistrar} implementations,
* as well as regular component classes (analogous to
* {@link AnnotationConfigApplicationContext#register}).
* {@link ImportBeanDefinitionRegistrar}, and {@link BeanRegistrar}/{@link DeferredBeanRegistrar}
* implementations, as well as regular component classes
* (analogous to {@link AnnotationConfigApplicationContext#register}).
*
* <p>{@code @Bean} definitions declared in imported {@code @Configuration} classes should be
* accessed by using {@link org.springframework.beans.factory.annotation.Autowired @Autowired}
@ -71,8 +72,9 @@ public @interface Import { @@ -71,8 +72,9 @@ public @interface Import {
/**
* {@link Configuration @Configuration}, {@link ImportSelector},
* {@link ImportBeanDefinitionRegistrar}, {@link BeanRegistrar}, or regular
* component classes to import.
* {@link ImportBeanDefinitionRegistrar},
* {@link BeanRegistrar}/{@link DeferredBeanRegistrar},
* or regular component classes to import.
*/
Class<?>[] value();

49
spring-context/src/main/java/org/springframework/context/support/GenericApplicationContext.java

@ -44,6 +44,10 @@ import org.springframework.beans.factory.support.DefaultListableBeanFactory; @@ -44,6 +44,10 @@ import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.DeferredBeanRegistrar;
import org.springframework.core.Ordered;
import org.springframework.core.PriorityOrdered;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.io.ProtocolResolver;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
@ -105,6 +109,10 @@ import org.springframework.util.Assert; @@ -105,6 +109,10 @@ import org.springframework.util.Assert;
*/
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
private static final String DEFERRED_REGISTRY_POST_PROCESSOR_BEAN_NAME =
GenericApplicationContext.class.getName() + ".deferredRegistryPostProcessor";
private final DefaultListableBeanFactory beanFactory;
private @Nullable ResourceLoader resourceLoader;
@ -604,7 +612,18 @@ public class GenericApplicationContext extends AbstractApplicationContext implem @@ -604,7 +612,18 @@ public class GenericApplicationContext extends AbstractApplicationContext implem
*/
public void register(BeanRegistrar... registrars) {
for (BeanRegistrar registrar : registrars) {
new BeanRegistryAdapter(this.beanFactory, getEnvironment(), registrar.getClass()).register(registrar);
if (registrar instanceof DeferredBeanRegistrar deferredRegistrar) {
DeferredRegistryPostProcessor pp = (DeferredRegistryPostProcessor)
this.beanFactory.getSingleton(DEFERRED_REGISTRY_POST_PROCESSOR_BEAN_NAME);
if (pp == null) {
pp = new DeferredRegistryPostProcessor();
this.beanFactory.registerSingleton(DEFERRED_REGISTRY_POST_PROCESSOR_BEAN_NAME, pp);
}
pp.addRegistrar(deferredRegistrar);
}
else {
new BeanRegistryAdapter(this.beanFactory, getEnvironment(), registrar.getClass()).register(registrar);
}
}
}
@ -648,4 +667,32 @@ public class GenericApplicationContext extends AbstractApplicationContext implem @@ -648,4 +667,32 @@ public class GenericApplicationContext extends AbstractApplicationContext implem
}
}
/**
* Internal post-processor for invoking DeferredBeanRegistrars at the end
* of the BeanDefinitionRegistryPostProcessor PriorityOrdered phase,
* right after a potential ConfigurationClassPostProcessor.
*/
private class DeferredRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor, PriorityOrdered {
private final List<DeferredBeanRegistrar> registrars = new ArrayList<>();
public void addRegistrar(DeferredBeanRegistrar registrar) {
this.registrars.add(registrar);
}
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE; // within PriorityOrdered, 1 behind ConfigurationClassPostProcessor
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
AnnotationAwareOrderComparator.sort(this.registrars);
for (DeferredBeanRegistrar registrar : this.registrars) {
new BeanRegistryAdapter(beanFactory, getEnvironment(), registrar.getClass()).register(registrar);
}
}
}
}

41
spring-context/src/test/java/org/springframework/context/annotation/beanregistrar/BeanRegistrarConfigurationTests.java

@ -22,6 +22,7 @@ import org.springframework.beans.factory.BeanRegistrar; @@ -22,6 +22,7 @@ import org.springframework.beans.factory.BeanRegistrar;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.testfixture.beans.TestBean;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.testfixture.beans.factory.BarRegistrar;
import org.springframework.context.testfixture.beans.factory.FooRegistrar;
@ -35,6 +36,9 @@ import org.springframework.context.testfixture.context.annotation.registrar.Bean @@ -35,6 +36,9 @@ import org.springframework.context.testfixture.context.annotation.registrar.Bean
import org.springframework.context.testfixture.context.annotation.registrar.GenericBeanRegistrarConfiguration;
import org.springframework.context.testfixture.context.annotation.registrar.ImportAwareBeanRegistrarConfiguration;
import org.springframework.context.testfixture.context.annotation.registrar.MultipleBeanRegistrarsConfiguration;
import org.springframework.context.testfixture.context.annotation.registrar.MyDeferredBeanRegistrarConfiguration;
import org.springframework.context.testfixture.context.annotation.registrar.MyRegularBeanRegistrarConfiguration;
import org.springframework.context.testfixture.context.annotation.registrar.TestBeanConfiguration;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
@ -105,4 +109,41 @@ class BeanRegistrarConfigurationTests { @@ -105,4 +109,41 @@ class BeanRegistrarConfigurationTests {
assertThat(context.getBean(BarRegistrar.Bar.class)).isNotNull();
}
@Test
void regularBeanRegistrarWithConditionMet() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(TestBeanConfiguration.class);
context.register(MyRegularBeanRegistrarConfiguration.class);
context.refresh();
assertThat(context.containsBean("myTestBean")).isTrue();
assertThat(context.getBean("myTestBean")).isInstanceOf(TestBean.class);
}
@Test
void regularBeanRegistrarWithConditionNotMet() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(MyRegularBeanRegistrarConfiguration.class);
context.register(TestBeanConfiguration.class);
context.refresh();
assertThat(context.containsBean("myTestBean")).isFalse();
}
@Test
void deferredBeanRegistrarWithConditionMet() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(MyDeferredBeanRegistrarConfiguration.class);
context.register(TestBeanConfiguration.class);
context.refresh();
assertThat(context.containsBean("myTestBean")).isTrue();
assertThat(context.getBean("myTestBean")).isInstanceOf(TestBean.class);
}
@Test
void deferredBeanRegistrarWithConditionNotMet() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(MyDeferredBeanRegistrarConfiguration.class);
context.refresh();
assertThat(context.containsBean("myTestBean")).isFalse();
}
}

40
spring-context/src/test/java/org/springframework/context/support/GenericApplicationContextTests.java

@ -44,9 +44,12 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder; @@ -44,9 +44,12 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.testfixture.beans.TestBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.testfixture.beans.factory.ImportAwareBeanRegistrar;
import org.springframework.context.testfixture.beans.factory.MyDeferredBeanRegistrar;
import org.springframework.context.testfixture.beans.factory.MyRegularBeanRegistrar;
import org.springframework.context.testfixture.beans.factory.SampleBeanRegistrar;
import org.springframework.core.DecoratingProxy;
import org.springframework.core.env.ConfigurableEnvironment;
@ -645,6 +648,43 @@ class GenericApplicationContextTests { @@ -645,6 +648,43 @@ class GenericApplicationContextTests {
assertThat(context.getBean(ImportAwareBeanRegistrar.ClassNameHolder.class).className()).isNull();
}
@Test
void regularBeanRegistrarWithConditionMet() {
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean("testBean", TestBean.class);
context.register(new MyRegularBeanRegistrar());
context.refresh();
assertThat(context.containsBean("myTestBean")).isTrue();
assertThat(context.getBean("myTestBean")).isInstanceOf(TestBean.class);
}
@Test
void regularBeanRegistrarWithConditionNotMet() {
GenericApplicationContext context = new GenericApplicationContext();
context.register(new MyRegularBeanRegistrar());
context.registerBean("testBean", TestBean.class);
context.refresh();
assertThat(context.containsBean("myTestBean")).isFalse();
}
@Test
void deferredBeanRegistrarWithConditionMet() {
GenericApplicationContext context = new GenericApplicationContext();
context.register(new MyDeferredBeanRegistrar());
context.registerBean("testBean", TestBean.class);
context.refresh();
assertThat(context.containsBean("myTestBean")).isTrue();
assertThat(context.getBean("myTestBean")).isInstanceOf(TestBean.class);
}
@Test
void deferredBeanRegistrarWithConditionNotMet() {
GenericApplicationContext context = new GenericApplicationContext();
context.register(new MyDeferredBeanRegistrar());
context.refresh();
assertThat(context.containsBean("myTestBean")).isFalse();
}
private MergedBeanDefinitionPostProcessor registerMockMergedBeanDefinitionPostProcessor(GenericApplicationContext context) {
MergedBeanDefinitionPostProcessor bpp = mock();

37
spring-context/src/testFixtures/java/org/springframework/context/testfixture/beans/factory/MyDeferredBeanRegistrar.java

@ -0,0 +1,37 @@ @@ -0,0 +1,37 @@
/*
* Copyright 2002-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.testfixture.beans.factory;
import org.springframework.beans.factory.BeanRegistry;
import org.springframework.beans.testfixture.beans.TestBean;
import org.springframework.context.DeferredBeanRegistrar;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.env.Environment;
public class MyDeferredBeanRegistrar implements DeferredBeanRegistrar {
@Override
public void register(BeanRegistry registry, Environment env) {
if (registry.containsBean("testBean") &&
registry.containsBean(TestBean.class) &&
registry.containsBean(new ParameterizedTypeReference<Comparable<Object>>() {
})) {
registry.registerBean("myTestBean", TestBean.class);
}
}
}

36
spring-context/src/testFixtures/java/org/springframework/context/testfixture/beans/factory/MyRegularBeanRegistrar.java

@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
/*
* Copyright 2002-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.testfixture.beans.factory;
import org.springframework.beans.factory.BeanRegistrar;
import org.springframework.beans.factory.BeanRegistry;
import org.springframework.beans.testfixture.beans.TestBean;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.env.Environment;
public class MyRegularBeanRegistrar implements BeanRegistrar {
@Override
public void register(BeanRegistry registry, Environment env) {
if (registry.containsBean("testBean") &&
registry.containsBean(TestBean.class) &&
registry.containsBean(new ParameterizedTypeReference<Comparable<Object>>() {
})) {
registry.registerBean("myTestBean", TestBean.class);
}
}
}

26
spring-context/src/testFixtures/java/org/springframework/context/testfixture/context/annotation/registrar/MyDeferredBeanRegistrarConfiguration.java

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
/*
* Copyright 2002-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.testfixture.context.annotation.registrar;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.testfixture.beans.factory.MyDeferredBeanRegistrar;
@Configuration
@Import(MyDeferredBeanRegistrar.class)
public class MyDeferredBeanRegistrarConfiguration {
}

26
spring-context/src/testFixtures/java/org/springframework/context/testfixture/context/annotation/registrar/MyRegularBeanRegistrarConfiguration.java

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
/*
* Copyright 2002-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.testfixture.context.annotation.registrar;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.testfixture.beans.factory.MyRegularBeanRegistrar;
@Configuration
@Import(MyRegularBeanRegistrar.class)
public class MyRegularBeanRegistrarConfiguration {
}

31
spring-context/src/testFixtures/java/org/springframework/context/testfixture/context/annotation/registrar/TestBeanConfiguration.java

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
/*
* Copyright 2002-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.testfixture.context.annotation.registrar;
import org.springframework.beans.testfixture.beans.TestBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class TestBeanConfiguration {
@Bean
public TestBean testBean() {
return new TestBean();
}
}
Loading…
Cancel
Save