From 35928520b8085739cfab8a889bc5a40c60f9abb8 Mon Sep 17 00:00:00 2001 From: Martin Kouba Date: Mon, 25 Apr 2022 10:38:22 +0200 Subject: [PATCH] ArC - optimize CreationalContext for synthetic dependent beans - do store a synthetic dependent instance in CC if the bean has no destruction logic - related to #25083 --- .../quarkus/arc/processor/BeanGenerator.java | 13 +---- .../DependentCreationalContextTest.java | 47 ++++++++++++++++++- 2 files changed, 47 insertions(+), 13 deletions(-) diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanGenerator.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanGenerator.java index 89ea7bc77e229..7b0baed226714 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanGenerator.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanGenerator.java @@ -1593,17 +1593,8 @@ protected void implementGet(BeanInfo bean, ClassCreator beanCreator, ProviderTyp // We can optimize if: // 1) class bean - has no @PreDestroy interceptor and there is no @PreDestroy callback // 2) producer - there is no disposal method - boolean canBeOptimized = false; - if (bean.isClassBean()) { - canBeOptimized = bean.getLifecycleInterceptors(InterceptionType.PRE_DESTROY).isEmpty() - && Beans.getCallbacks(bean.getTarget().get().asClass(), - DotNames.PRE_DESTROY, - bean.getDeployment().getBeanArchiveIndex()).isEmpty(); - } else if (bean.isProducerMethod() || bean.isProducerField()) { - canBeOptimized = bean.getDisposer() == null; - } - - if (canBeOptimized) { + // 3) synthetic bean - has no destruction logic + if (!bean.hasDestroyLogic()) { // If there is no dependency in the creational context we don't have to store the instance in the CreationalContext ResultHandle creationalContext = get.checkCast(get.getMethodParam(0), CreationalContextImpl.class); get.ifNonZero( diff --git a/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/contexts/dependent/DependentCreationalContextTest.java b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/contexts/dependent/DependentCreationalContextTest.java index 00525509dff12..350dcae44f5a7 100644 --- a/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/contexts/dependent/DependentCreationalContextTest.java +++ b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/contexts/dependent/DependentCreationalContextTest.java @@ -5,10 +5,15 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import io.quarkus.arc.Arc; +import io.quarkus.arc.BeanCreator; +import io.quarkus.arc.BeanDestroyer; import io.quarkus.arc.impl.InstanceImpl; +import io.quarkus.arc.processor.BeanRegistrar; import io.quarkus.arc.test.ArcTestContainer; +import java.util.Map; import javax.annotation.PreDestroy; import javax.enterprise.context.Dependent; +import javax.enterprise.context.spi.CreationalContext; import javax.enterprise.inject.Disposes; import javax.enterprise.inject.Produces; import javax.inject.Inject; @@ -18,8 +23,19 @@ public class DependentCreationalContextTest { @RegisterExtension - ArcTestContainer container = new ArcTestContainer(NoPreDestroy.class, HasDestroy.class, HasDependency.class, - ProducerNoDisposer.class, ProducerWithDisposer.class, String.class, Boolean.class); + ArcTestContainer container = ArcTestContainer.builder() + .beanClasses(NoPreDestroy.class, HasDestroy.class, HasDependency.class, + ProducerNoDisposer.class, ProducerWithDisposer.class, String.class, Boolean.class) + .beanRegistrars(new BeanRegistrar() { + + @Override + public void register(RegistrationContext context) { + context.configure(SyntheticOne.class).addType(SyntheticOne.class).creator(SyntheticOne.class).done(); + context.configure(SyntheticTwo.class).addType(SyntheticTwo.class).creator(SyntheticTwo.class) + .destroyer(SyntheticTwo.class).done(); + } + }) + .build(); @Test public void testCreationalContextOptimization() { @@ -31,6 +47,10 @@ public void testCreationalContextOptimization() { assertBeanType(instance, boolean.class, false); // ProducerWithDisposer assertBeanType(instance, String.class, true); + // Synthetic bean + assertBeanType(instance, SyntheticOne.class, false); + // Synthetic bean with destruction logic + assertBeanType(instance, SyntheticTwo.class, true); } void assertBeanType(InstanceImpl instance, Class beanType, boolean shouldBeStored) { @@ -88,4 +108,27 @@ void dispose(@Disposes String ping) { } } + + public static class SyntheticOne implements BeanCreator { + + @Override + public SyntheticOne create(CreationalContext creationalContext, Map params) { + return new SyntheticOne(); + } + + } + + public static class SyntheticTwo implements BeanCreator, BeanDestroyer { + + @Override + public SyntheticTwo create(CreationalContext creationalContext, Map params) { + return new SyntheticTwo(); + } + + @Override + public void destroy(SyntheticTwo instance, CreationalContext creationalContext, + Map params) { + } + + } }