GH-1498: early steps to index bean registrations from bean registrars
This commit is contained in:
@@ -99,6 +99,10 @@ public class Annotations {
|
|||||||
public static final String APPLICATION_LISTENER = "org.springframework.context.ApplicationListener";
|
public static final String APPLICATION_LISTENER = "org.springframework.context.ApplicationListener";
|
||||||
public static final String EVENT_PUBLISHER = "org.springframework.context.ApplicationEventPublisher";
|
public static final String EVENT_PUBLISHER = "org.springframework.context.ApplicationEventPublisher";
|
||||||
|
|
||||||
|
public static final String BEAN_REGISTRAR_INTERFACE = "org.springframework.beans.factory.BeanRegistrar";
|
||||||
|
public static final String BEAN_REGISTRY_INTERFACE = "org.springframework.beans.factory.BeanRegistry";
|
||||||
|
|
||||||
|
|
||||||
public static final Map<String, String> AOP_ANNOTATIONS = Map.of(
|
public static final Map<String, String> AOP_ANNOTATIONS = Map.of(
|
||||||
"org.aspectj.lang.annotation.Pointcut", "Pointcut",
|
"org.aspectj.lang.annotation.Pointcut", "Pointcut",
|
||||||
"org.aspectj.lang.annotation.Before", "Before",
|
"org.aspectj.lang.annotation.Before", "Before",
|
||||||
@@ -108,7 +112,6 @@ public class Annotations {
|
|||||||
"org.aspectj.lang.annotation.AfterThrowing", "AfterThrowing",
|
"org.aspectj.lang.annotation.AfterThrowing", "AfterThrowing",
|
||||||
"org.aspectj.lang.annotation.DeclareParents", "DeclareParents"
|
"org.aspectj.lang.annotation.DeclareParents", "DeclareParents"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.springframework.ide.vscode.boot.java.beans;
|
package org.springframework.ide.vscode.boot.java.beans;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@@ -18,9 +19,11 @@ import java.util.Set;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.core.dom.ASTNode;
|
||||||
import org.eclipse.jdt.core.dom.ASTVisitor;
|
import org.eclipse.jdt.core.dom.ASTVisitor;
|
||||||
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
|
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
|
||||||
import org.eclipse.jdt.core.dom.Annotation;
|
import org.eclipse.jdt.core.dom.Annotation;
|
||||||
|
import org.eclipse.jdt.core.dom.Block;
|
||||||
import org.eclipse.jdt.core.dom.Expression;
|
import org.eclipse.jdt.core.dom.Expression;
|
||||||
import org.eclipse.jdt.core.dom.IMethodBinding;
|
import org.eclipse.jdt.core.dom.IMethodBinding;
|
||||||
import org.eclipse.jdt.core.dom.ITypeBinding;
|
import org.eclipse.jdt.core.dom.ITypeBinding;
|
||||||
@@ -140,6 +143,7 @@ public class ComponentSymbolProvider implements SymbolProvider {
|
|||||||
indexEventListenerInterfaceImplementation(beanDefinition, type, context, doc);
|
indexEventListenerInterfaceImplementation(beanDefinition, type, context, doc);
|
||||||
indexRequestMappings(beanDefinition, type, annotationType, metaAnnotations, context, doc);
|
indexRequestMappings(beanDefinition, type, annotationType, metaAnnotations, context, doc);
|
||||||
indexConfigurationProperties(beanDefinition, type, context, doc);
|
indexConfigurationProperties(beanDefinition, type, context, doc);
|
||||||
|
indexBeanRegistrarImplementation(beanDefinition, type, context, doc);
|
||||||
|
|
||||||
context.getGeneratedSymbols().add(new CachedSymbol(context.getDocURI(), context.getLastModified(), symbol));
|
context.getGeneratedSymbols().add(new CachedSymbol(context.getDocURI(), context.getLastModified(), symbol));
|
||||||
context.getBeans().add(new CachedBean(context.getDocURI(), beanDefinition));
|
context.getBeans().add(new CachedBean(context.getDocURI(), beanDefinition));
|
||||||
@@ -321,6 +325,7 @@ public class ComponentSymbolProvider implements SymbolProvider {
|
|||||||
// check for event listener implementations on classes that are not annotated with component, but created via bean methods (for example)
|
// check for event listener implementations on classes that are not annotated with component, but created via bean methods (for example)
|
||||||
if (!isComponment) {
|
if (!isComponment) {
|
||||||
indexEventListenerInterfaceImplementation(null, typeDeclaration, context, doc);
|
indexEventListenerInterfaceImplementation(null, typeDeclaration, context, doc);
|
||||||
|
indexBeanRegistrarImplementation(null, typeDeclaration, context, doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -377,6 +382,191 @@ public class ComponentSymbolProvider implements SymbolProvider {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private MethodDeclaration findRegisterMethod(TypeDeclaration type, ITypeBinding beanRegistrarType) {
|
||||||
|
IMethodBinding[] beanRegistrarMethods = beanRegistrarType.getDeclaredMethods();
|
||||||
|
if (beanRegistrarMethods == null || beanRegistrarMethods.length != 1 || !"register".equals(beanRegistrarMethods[0].getName())) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
MethodDeclaration[] methods = type.getMethods();
|
||||||
|
|
||||||
|
for (MethodDeclaration method : methods) {
|
||||||
|
IMethodBinding binding = method.resolveBinding();
|
||||||
|
boolean overrides = binding.overrides(beanRegistrarMethods[0]);
|
||||||
|
if (overrides) {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void indexBeanRegistrarImplementation(Bean bean, TypeDeclaration typeDeclaration, SpringIndexerJavaContext context, TextDocument doc) {
|
||||||
|
try {
|
||||||
|
ITypeBinding typeBinding = typeDeclaration.resolveBinding();
|
||||||
|
if (typeBinding == null) return;
|
||||||
|
|
||||||
|
ITypeBinding inTypeHierarchy = ASTUtils.findInTypeHierarchy(typeDeclaration, doc, typeBinding, Set.of(Annotations.BEAN_REGISTRAR_INTERFACE));
|
||||||
|
if (inTypeHierarchy == null) return;
|
||||||
|
|
||||||
|
MethodDeclaration registerMethod = findRegisterMethod(typeDeclaration, inTypeHierarchy);
|
||||||
|
if (registerMethod == null) return;
|
||||||
|
|
||||||
|
if (!context.isFullAst()) { // needs full method bodies to continue
|
||||||
|
throw new RequiredCompleteAstException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bean == null) { // need to create and register bean element
|
||||||
|
String beanType = typeBinding.getQualifiedName();
|
||||||
|
String beanName = BeanUtils.getBeanNameFromType(typeBinding.getName());
|
||||||
|
|
||||||
|
Location location = new Location(doc.getUri(), doc.toRange(typeDeclaration.getStartPosition(), typeDeclaration.getLength()));
|
||||||
|
|
||||||
|
WorkspaceSymbol symbol = new WorkspaceSymbol(
|
||||||
|
beanLabel("+", null, null, beanName, beanType),
|
||||||
|
SymbolKind.Class,
|
||||||
|
Either.forLeft(location));
|
||||||
|
|
||||||
|
InjectionPoint[] injectionPoints = ASTUtils.findInjectionPoints(typeDeclaration, doc);
|
||||||
|
|
||||||
|
Set<String> supertypes = new HashSet<>();
|
||||||
|
ASTUtils.findSupertypes(typeBinding, supertypes);
|
||||||
|
|
||||||
|
Collection<Annotation> annotationsOnMethod = ASTUtils.getAnnotations(typeDeclaration);
|
||||||
|
AnnotationMetadata[] annotations = ASTUtils.getAnnotationsMetadata(annotationsOnMethod, doc);
|
||||||
|
|
||||||
|
bean = new Bean(beanName, beanType, location, injectionPoints, supertypes, annotations, false, symbol.getName());
|
||||||
|
|
||||||
|
context.getGeneratedSymbols().add(new CachedSymbol(context.getDocURI(), context.getLastModified(), symbol));
|
||||||
|
context.getBeans().add(new CachedBean(context.getDocURI(), bean));
|
||||||
|
}
|
||||||
|
|
||||||
|
scanBeanRegistryInvocations(bean, registerMethod.getBody(), context, doc);
|
||||||
|
|
||||||
|
} catch (BadLocationException e) {
|
||||||
|
log.error("", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void scanBeanRegistryInvocations(Bean component, Block body, SpringIndexerJavaContext context, TextDocument doc) {
|
||||||
|
if (body == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.accept(new ASTVisitor() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(MethodInvocation methodInvocation) {
|
||||||
|
try {
|
||||||
|
String methodName = methodInvocation.getName().toString();
|
||||||
|
if ("registerBean".equals(methodName)) {
|
||||||
|
|
||||||
|
IMethodBinding methodBinding = methodInvocation.resolveMethodBinding();
|
||||||
|
ITypeBinding declaringClass = methodBinding.getDeclaringClass();
|
||||||
|
|
||||||
|
if (declaringClass != null && Annotations.BEAN_REGISTRY_INTERFACE.equals(declaringClass.getQualifiedName())) {
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
List<Expression> arguments = methodInvocation.arguments();
|
||||||
|
List<ITypeBinding> types = new ArrayList<>();
|
||||||
|
|
||||||
|
for (Expression argument : arguments) {
|
||||||
|
ITypeBinding typeBinding = argument.resolveTypeBinding();
|
||||||
|
if (typeBinding != null) {
|
||||||
|
types.add(typeBinding);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arguments.size() == 1 && "java.lang.Class".equals(types.get(0).getBinaryName())) {
|
||||||
|
// <T> String registerBean(Class<T> beanClass);
|
||||||
|
|
||||||
|
ITypeBinding typeBinding = types.get(0);
|
||||||
|
ITypeBinding[] typeParameters = typeBinding.getTypeArguments();
|
||||||
|
if (typeParameters != null && typeParameters.length == 1) {
|
||||||
|
String typeParamName = typeParameters[0].getBinaryName();
|
||||||
|
|
||||||
|
String beanName = BeanUtils.getBeanNameFromType(typeParameters[0].getName());
|
||||||
|
String beanType = typeParamName;
|
||||||
|
|
||||||
|
createBean(component, beanName, beanType, typeParameters[0], methodInvocation, context, doc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (arguments.size() == 2 && "java.lang.String".equals(types.get(0).getQualifiedName()) && "java.lang.Class".equals(types.get(1).getBinaryName())) {
|
||||||
|
// <T> void registerBean(String name, Class<T> beanClass);
|
||||||
|
|
||||||
|
String beanName = ASTUtils.getExpressionValueAsString(arguments.get(0), (dep) -> {});
|
||||||
|
|
||||||
|
ITypeBinding typeBinding = types.get(1);
|
||||||
|
ITypeBinding[] typeParameters = typeBinding.getTypeArguments();
|
||||||
|
if (typeParameters != null && typeParameters.length == 1) {
|
||||||
|
String typeParamName = typeParameters[0].getBinaryName();
|
||||||
|
String beanType = typeParamName;
|
||||||
|
|
||||||
|
createBean(component, beanName, beanType, typeParameters[0], methodInvocation, context, doc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (arguments.size() == 2 && "java.lang.Class".equals(types.get(0).getBinaryName()) && "java.util.function.Consumer".equals(types.get(1).getBinaryName())) {
|
||||||
|
// <T> String registerBean(Class<T> beanClass, Consumer<Spec<T>> customizer);
|
||||||
|
|
||||||
|
ITypeBinding typeBinding = types.get(0);
|
||||||
|
ITypeBinding[] typeParameters = typeBinding.getTypeArguments();
|
||||||
|
if (typeParameters != null && typeParameters.length == 1) {
|
||||||
|
String typeParamName = typeParameters[0].getBinaryName();
|
||||||
|
|
||||||
|
String beanName = BeanUtils.getBeanNameFromType(typeParameters[0].getName());
|
||||||
|
String beanType = typeParamName;
|
||||||
|
|
||||||
|
createBean(component, beanName, beanType, typeParameters[0], methodInvocation, context, doc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (arguments.size() == 3 && "java.lang.String".equals(types.get(0).getQualifiedName())
|
||||||
|
&& "java.lang.Class".equals(types.get(1).getBinaryName()) && "java.util.function.Consumer".equals(types.get(2).getBinaryName())) {
|
||||||
|
// <T> void registerBean(String name, Class<T> beanClass, Consumer<Spec<T>> customizer);
|
||||||
|
|
||||||
|
String beanName = ASTUtils.getExpressionValueAsString(arguments.get(0), (dep) -> {});
|
||||||
|
|
||||||
|
ITypeBinding typeBinding = types.get(1);
|
||||||
|
ITypeBinding[] typeParameters = typeBinding.getTypeArguments();
|
||||||
|
if (typeParameters != null && typeParameters.length == 1) {
|
||||||
|
String typeParamName = typeParameters[0].getBinaryName();
|
||||||
|
String beanType = typeParamName;
|
||||||
|
|
||||||
|
createBean(component, beanName, beanType, typeParameters[0], methodInvocation, context, doc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (BadLocationException e) {
|
||||||
|
log.error("", e);
|
||||||
|
}
|
||||||
|
return super.visit(methodInvocation);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createBean(Bean parentBean, String beanName, String beanType, ITypeBinding beanTypeBinding, ASTNode node, SpringIndexerJavaContext context, TextDocument doc) throws BadLocationException {
|
||||||
|
Location location = new Location(doc.getUri(), doc.toRange(node.getStartPosition(), node.getLength()));
|
||||||
|
|
||||||
|
WorkspaceSymbol symbol = new WorkspaceSymbol(
|
||||||
|
beanLabel("+", null, null, beanName, beanType),
|
||||||
|
SymbolKind.Class,
|
||||||
|
Either.forLeft(location));
|
||||||
|
context.getGeneratedSymbols().add(new CachedSymbol(context.getDocURI(), context.getLastModified(), symbol));
|
||||||
|
|
||||||
|
InjectionPoint[] injectionPoints = DefaultValues.EMPTY_INJECTION_POINTS;
|
||||||
|
Set<String> supertypes = new HashSet<>();
|
||||||
|
ASTUtils.findSupertypes(beanTypeBinding, supertypes);
|
||||||
|
|
||||||
|
AnnotationMetadata[] annotations = DefaultValues.EMPTY_ANNOTATIONS;
|
||||||
|
|
||||||
|
Bean bean = new Bean(beanName, beanType, location, injectionPoints, supertypes, annotations, false, symbol.getName());
|
||||||
|
parentBean.addChild(bean);
|
||||||
|
}
|
||||||
|
|
||||||
public static String beanLabel(String searchPrefix, String annotationTypeName, Collection<String> metaAnnotationNames, String beanName, String beanType) {
|
public static String beanLabel(String searchPrefix, String annotationTypeName, Collection<String> metaAnnotationNames, String beanName, String beanType) {
|
||||||
StringBuilder symbolLabel = new StringBuilder();
|
StringBuilder symbolLabel = new StringBuilder();
|
||||||
symbolLabel.append("@");
|
symbolLabel.append("@");
|
||||||
@@ -385,21 +575,25 @@ public class ComponentSymbolProvider implements SymbolProvider {
|
|||||||
symbolLabel.append('\'');
|
symbolLabel.append('\'');
|
||||||
symbolLabel.append(beanName);
|
symbolLabel.append(beanName);
|
||||||
symbolLabel.append('\'');
|
symbolLabel.append('\'');
|
||||||
symbolLabel.append(" (@");
|
|
||||||
symbolLabel.append(annotationTypeName);
|
if (annotationTypeName != null) {
|
||||||
if (!metaAnnotationNames.isEmpty()) {
|
symbolLabel.append(" (@");
|
||||||
symbolLabel.append(" <: ");
|
symbolLabel.append(annotationTypeName);
|
||||||
boolean first = true;
|
if (!metaAnnotationNames.isEmpty()) {
|
||||||
for (String ma : metaAnnotationNames) {
|
symbolLabel.append(" <: ");
|
||||||
if (!first) {
|
boolean first = true;
|
||||||
symbolLabel.append(", ");
|
for (String ma : metaAnnotationNames) {
|
||||||
|
if (!first) {
|
||||||
|
symbolLabel.append(", ");
|
||||||
|
}
|
||||||
|
symbolLabel.append("@");
|
||||||
|
symbolLabel.append(ma);
|
||||||
|
first = false;
|
||||||
}
|
}
|
||||||
symbolLabel.append("@");
|
|
||||||
symbolLabel.append(ma);
|
|
||||||
first = false;
|
|
||||||
}
|
}
|
||||||
|
symbolLabel.append(")");
|
||||||
}
|
}
|
||||||
symbolLabel.append(") ");
|
symbolLabel.append(" ");
|
||||||
symbolLabel.append(beanType);
|
symbolLabel.append(beanType);
|
||||||
return symbolLabel.toString();
|
return symbolLabel.toString();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -403,7 +403,7 @@ public class ASTUtils {
|
|||||||
simplifiedType = resolvedInterface.getBinaryName();
|
simplifiedType = resolvedInterface.getBinaryName();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
simplifiedType = resolvedType.getQualifiedName();
|
simplifiedType = resolvedInterface.getQualifiedName();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typesToCheck.contains(simplifiedType)) {
|
if (typesToCheck.contains(simplifiedType)) {
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2025 Broadcom
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* https://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Broadcom - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.springframework.ide.vscode.boot.index.test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.eclipse.lsp4j.TextDocumentIdentifier;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Import;
|
||||||
|
import org.springframework.ide.vscode.boot.app.SpringSymbolIndex;
|
||||||
|
import org.springframework.ide.vscode.boot.bootiful.BootLanguageServerTest;
|
||||||
|
import org.springframework.ide.vscode.boot.bootiful.SymbolProviderTestConf;
|
||||||
|
import org.springframework.ide.vscode.boot.index.SpringMetamodelIndex;
|
||||||
|
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
|
||||||
|
import org.springframework.ide.vscode.commons.protocol.spring.Bean;
|
||||||
|
import org.springframework.ide.vscode.commons.protocol.spring.SpringIndexElement;
|
||||||
|
import org.springframework.ide.vscode.project.harness.BootLanguageServerHarness;
|
||||||
|
import org.springframework.ide.vscode.project.harness.ProjectsHarness;
|
||||||
|
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Martin Lippert
|
||||||
|
*/
|
||||||
|
@ExtendWith(SpringExtension.class)
|
||||||
|
@BootLanguageServerTest
|
||||||
|
@Import(SymbolProviderTestConf.class)
|
||||||
|
public class SpringIndexerBeanRegistrarTest {
|
||||||
|
|
||||||
|
@Autowired private BootLanguageServerHarness harness;
|
||||||
|
@Autowired private JavaProjectFinder projectFinder;
|
||||||
|
@Autowired private SpringSymbolIndex indexer;
|
||||||
|
@Autowired private SpringMetamodelIndex springIndex;
|
||||||
|
|
||||||
|
private File directory;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setup() throws Exception {
|
||||||
|
harness.intialize(null);
|
||||||
|
|
||||||
|
directory = new File(ProjectsHarness.class.getResource("/test-projects/test-framework-7-indexing/").toURI());
|
||||||
|
|
||||||
|
String projectDir = directory.toURI().toString();
|
||||||
|
|
||||||
|
// trigger project creation
|
||||||
|
projectFinder.find(new TextDocumentIdentifier(projectDir)).get();
|
||||||
|
|
||||||
|
CompletableFuture<Void> initProject = indexer.waitOperation();
|
||||||
|
initProject.get(5, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSimpleBeanRegistration() throws Exception {
|
||||||
|
String docUri = directory.toPath().resolve("src/main/java/com/example/MyBeanRegistrar.java").toUri().toString();
|
||||||
|
|
||||||
|
Bean[] beans = springIndex.getBeansOfDocument(docUri);
|
||||||
|
assertEquals(5, beans.length);
|
||||||
|
|
||||||
|
Bean beanRegistrarBean = Arrays.stream(beans).filter(bean -> bean.getName().equals("myBeanRegistrar")).findFirst().get();
|
||||||
|
assertEquals("com.example.MyBeanRegistrar", beanRegistrarBean.getType());
|
||||||
|
|
||||||
|
List<SpringIndexElement> children = beanRegistrarBean.getChildren();
|
||||||
|
assertEquals(4, children.size());
|
||||||
|
|
||||||
|
Bean fooFoo = (Bean) children.get(0);
|
||||||
|
assertEquals("fooFoo", fooFoo.getName());
|
||||||
|
assertEquals("com.example.FooFoo", fooFoo.getType());
|
||||||
|
|
||||||
|
Bean foo = (Bean) children.get(1);
|
||||||
|
assertEquals("foo", foo.getName());
|
||||||
|
assertEquals("com.example.Foo", foo.getType());
|
||||||
|
|
||||||
|
Bean bar = (Bean) children.get(2);
|
||||||
|
assertEquals("bar", bar.getName());
|
||||||
|
assertEquals("com.example.Bar", bar.getType());
|
||||||
|
|
||||||
|
Bean baz = (Bean) children.get(3);
|
||||||
|
assertEquals("baz", baz.getName());
|
||||||
|
assertEquals("com.example.Baz", baz.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -6,19 +6,19 @@ import org.springframework.core.env.Environment;
|
|||||||
|
|
||||||
public class MyBeanRegistrar implements BeanRegistrar {
|
public class MyBeanRegistrar implements BeanRegistrar {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void register(BeanRegistry registry, Environment env) {
|
public void register(BeanRegistry registry, Environment env) {
|
||||||
registry.registerBean(FooFoo.class);
|
registry.registerBean(FooFoo.class);
|
||||||
registry.registerBean("foo", Foo.class);
|
registry.registerBean("foo", Foo.class);
|
||||||
registry.registerBean("bar", Bar.class, spec -> spec
|
registry.registerBean("bar", Bar.class, spec -> spec
|
||||||
.prototype()
|
.prototype()
|
||||||
.lazyInit()
|
.lazyInit()
|
||||||
.description("Custom description")
|
.description("Custom description")
|
||||||
.supplier(context -> new Bar(context.bean(Foo.class))));
|
.supplier(context -> new Bar(context.bean(Foo.class))));
|
||||||
if (env.matchesProfiles("baz")) {
|
if (env.matchesProfiles("baz")) {
|
||||||
registry.registerBean(Baz.class, spec -> spec
|
registry.registerBean(Baz.class, spec -> spec
|
||||||
.supplier(context -> new Baz("Hello World!")));
|
.supplier(context -> new Baz("Hello World!")));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user