Supplier registration support for annotated bean classes
Issue: SPR-14832
This commit is contained in:
@@ -17,7 +17,9 @@
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
|
||||
import org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.support.AutowireCandidateQualifier;
|
||||
@@ -83,6 +85,7 @@ public class AnnotatedBeanDefinitionReader {
|
||||
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the BeanDefinitionRegistry that this scanner operates on.
|
||||
*/
|
||||
@@ -117,28 +120,94 @@ public class AnnotatedBeanDefinitionReader {
|
||||
(scopeMetadataResolver != null ? scopeMetadataResolver : new AnnotationScopeMetadataResolver());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register one or more annotated classes to be processed.
|
||||
* <p>Calls to {@code register} are idempotent; adding the same
|
||||
* annotated class more than once has no additional effect.
|
||||
* @param annotatedClasses one or more annotated classes,
|
||||
* e.g. {@link Configuration @Configuration} classes
|
||||
*/
|
||||
public void register(Class<?>... annotatedClasses) {
|
||||
for (Class<?> annotatedClass : annotatedClasses) {
|
||||
registerBean(annotatedClass);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a bean from the given bean class, deriving its metadata from
|
||||
* class-declared annotations.
|
||||
* @param annotatedClass the class of the bean
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void registerBean(Class<?> annotatedClass) {
|
||||
registerBean(annotatedClass, null, (Class<? extends Annotation>[]) null);
|
||||
registerBean(annotatedClass, null, null, (Class<? extends Annotation>[]) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a bean from the given bean class, deriving its metadata from
|
||||
* class-declared annotations.
|
||||
* @param annotatedClass the class of the bean
|
||||
* @param qualifiers specific qualifier annotations to consider,
|
||||
* in addition to qualifiers at the bean class level
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void registerBean(Class<?> annotatedClass, Class<? extends Annotation>... qualifiers) {
|
||||
registerBean(annotatedClass, null, qualifiers);
|
||||
registerBean(annotatedClass, null, null, qualifiers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a bean from the given bean class, deriving its metadata from
|
||||
* class-declared annotations.
|
||||
* @param annotatedClass the class of the bean
|
||||
* @param name an explicit name for the bean
|
||||
* @param qualifiers specific qualifier annotations to consider,
|
||||
* in addition to qualifiers at the bean class level
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void registerBean(Class<?> annotatedClass, String name, Class<? extends Annotation>... qualifiers) {
|
||||
registerBean(annotatedClass, null, name, qualifiers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a bean from the given bean class, deriving its metadata from
|
||||
* class-declared annotations, using the given supplier for obtaining a new
|
||||
* instance (possibly declared as a lambda expression or method reference).
|
||||
* @param annotatedClass the class of the bean
|
||||
* @param instanceSupplier a callback for creating an instance of the bean
|
||||
* (may be {@code null})
|
||||
* @return the registered bean definition, or {@code null} if skipped due to
|
||||
* a declared condition
|
||||
* @since 5.0
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> AnnotatedBeanDefinition registerBean(Class<T> annotatedClass, Supplier<T> instanceSupplier) {
|
||||
return registerBean(annotatedClass, instanceSupplier, null, (Class<? extends Annotation>[]) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a bean from the given bean class, deriving its metadata from
|
||||
* class-declared annotations.
|
||||
* @param annotatedClass the class of the bean
|
||||
* @param instanceSupplier a callback for creating an instance of the bean
|
||||
* (may be {@code null})
|
||||
* @param name an explicit name for the bean
|
||||
* @param qualifiers specific qualifier annotations to consider, if any,
|
||||
* in addition to qualifiers at the bean class level
|
||||
* @return the registered bean definition, or {@code null} if skipped due to
|
||||
* a declared condition
|
||||
* @since 5.0
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> AnnotatedBeanDefinition registerBean(Class<T> annotatedClass, Supplier<T> instanceSupplier,
|
||||
String name, Class<? extends Annotation>... qualifiers) {
|
||||
|
||||
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
|
||||
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
abd.setInstanceSupplier(instanceSupplier);
|
||||
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
|
||||
abd.setScope(scopeMetadata.getScopeName());
|
||||
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
|
||||
@@ -160,6 +229,7 @@ public class AnnotatedBeanDefinitionReader {
|
||||
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
|
||||
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
|
||||
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
|
||||
return abd;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanNameGenerator;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
@@ -135,6 +138,16 @@ public class AnnotationConfigApplicationContext extends GenericApplicationContex
|
||||
this.scanner.setScopeMetadataResolver(scopeMetadataResolver);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void prepareRefresh() {
|
||||
this.scanner.clearCache();
|
||||
super.prepareRefresh();
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Implementation of AnnotationConfigRegistry
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Register one or more annotated classes to be processed.
|
||||
@@ -164,10 +177,78 @@ public class AnnotationConfigApplicationContext extends GenericApplicationContex
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void prepareRefresh() {
|
||||
this.scanner.clearCache();
|
||||
super.prepareRefresh();
|
||||
//---------------------------------------------------------------------
|
||||
// Convenient methods for registering individual beans
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Register a bean from the given bean class, deriving its metadata from
|
||||
* class-declared annotations, using the given supplier for obtaining a new
|
||||
* instance (possibly declared as a lambda expression or method reference).
|
||||
* <p>The bean name will be generated according to annotated component rules.
|
||||
* @param annotatedClass the class of the bean
|
||||
* @param instanceSupplier a callback for creating an instance of the bean
|
||||
* @since 5.0
|
||||
* @see #setBeanNameGenerator
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> void registerBean(Class<T> annotatedClass, Supplier<T> instanceSupplier) {
|
||||
registerBean(null, annotatedClass, instanceSupplier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a bean from the given bean class, deriving its metadata from
|
||||
* class-declared annotations, using the given supplier for obtaining a new
|
||||
* instance (possibly declared as a lambda expression or method reference).
|
||||
* @param beanName the name of the bean (may be {@code null})
|
||||
* @param annotatedClass the class of the bean
|
||||
* @param instanceSupplier a callback for creating an instance of the bean
|
||||
* @since 5.0
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> void registerBean(String beanName, Class<T> annotatedClass, Supplier<T> instanceSupplier) {
|
||||
Assert.notNull(instanceSupplier, "Supplier must not be null");
|
||||
this.reader.registerBean(annotatedClass, instanceSupplier, beanName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a bean from the given bean class, deriving its metadata from
|
||||
* class-declared annotations, and optionally providing explicit constructor
|
||||
* arguments for consideration in the autowiring process.
|
||||
* <p>The bean name will be generated according to annotated component rules.
|
||||
* @param annotatedClass the class of the bean
|
||||
* @param constructorArguments argument values to be fed into Spring's
|
||||
* constructor resolution algorithm, resolving either all arguments or just
|
||||
* specific ones, with the rest to be resolved through regular autowiring
|
||||
* (may be {@code null} or empty)
|
||||
* @since 5.0
|
||||
* @see #setBeanNameGenerator
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> void registerBean(Class<T> annotatedClass, Object... constructorArguments) {
|
||||
registerBean(null, annotatedClass, constructorArguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a bean from the given bean class, deriving its metadata from
|
||||
* class-declared annotations, and optionally providing explicit constructor
|
||||
* arguments for consideration in the autowiring process.
|
||||
* @param beanName the name of the bean (may be {@code null})
|
||||
* @param annotatedClass the class of the bean
|
||||
* @param constructorArguments argument values to be fed into Spring's
|
||||
* constructor resolution algorithm, resolving either all arguments or just
|
||||
* specific ones, with the rest to be resolved through regular autowiring
|
||||
* (may be {@code null} or empty)
|
||||
* @since 5.0
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> void registerBean(String beanName, Class<T> annotatedClass, Object... constructorArguments) {
|
||||
AnnotatedBeanDefinition abd = this.reader.registerBean(annotatedClass, null, beanName);
|
||||
if (constructorArguments != null) {
|
||||
for (Object arg : constructorArguments) {
|
||||
abd.getConstructorArgumentValues().addGenericArgumentValue(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user