You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwebbeans.apache.org by ta...@apache.org on 2026/07/28 15:20:57 UTC
(openwebbeans) branch main updated: OWB-1463 - cache by name and optimized loop
This is an automated email from the ASF dual-hosted git repository.
tandraschko pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/openwebbeans.git
The following commit(s) were added to refs/heads/main by this push:
new 9b7beb729 OWB-1463 - cache by name and optimized loop
9b7beb729 is described below
commit 9b7beb729b26c273baa39e668a751b1eaf85f218
Author: tandraschko <ta...@apache.org>
AuthorDate: Tue Jul 28 17:20:45 2026 +0200
OWB-1463 - cache by name and optimized loop
---
.../webbeans/container/InjectionResolver.java | 79 ++++++++++++++++++----
1 file changed, 65 insertions(+), 14 deletions(-)
diff --git a/webbeans-impl/src/main/java/org/apache/webbeans/container/InjectionResolver.java b/webbeans-impl/src/main/java/org/apache/webbeans/container/InjectionResolver.java
index 738e7f608..0c76ec2fc 100644
--- a/webbeans-impl/src/main/java/org/apache/webbeans/container/InjectionResolver.java
+++ b/webbeans-impl/src/main/java/org/apache/webbeans/container/InjectionResolver.java
@@ -103,6 +103,13 @@ public class InjectionResolver
*/
private volatile Map<Class<?>, Set<Bean<?>>> beansByRawType;
+ /**
+ * Index of all beans by their EL name.
+ * Built lazily once the bean set is final (post startup) so name based resolution can look up
+ * candidate beans instead of linearly scanning the whole deployment. Reset in {@link #clearCaches()}.
+ */
+ private volatile Map<String, Set<Bean<?>>> beansByName;
+
/**
* Whether the container is in startup mode.
* Set to {@code false} immediately before the BeforeDeploymentValidation event gets fired.
@@ -147,6 +154,7 @@ public class InjectionResolver
resolvedBeansByName.clear();
resolvedBeansByType.clear();
beansByRawType = null;
+ beansByName = null;
}
/**
@@ -183,6 +191,32 @@ public class InjectionResolver
return index;
}
+ private Map<String, Set<Bean<?>>> getBeansByName()
+ {
+ Map<String, Set<Bean<?>>> index = beansByName;
+ if (index == null)
+ {
+ synchronized (this)
+ {
+ index = beansByName;
+ if (index == null)
+ {
+ index = new HashMap<>();
+ for (Bean<?> bean : webBeansContext.getBeanManagerImpl().getBeans())
+ {
+ String beanName = bean.getName();
+ if (beanName != null)
+ {
+ index.computeIfAbsent(beanName, k -> new HashSet<>()).add(bean);
+ }
+ }
+ beansByName = index;
+ }
+ }
+ }
+ return index;
+ }
+
/**
* Check the type of the injection point.
* <p>
@@ -360,17 +394,29 @@ public class InjectionResolver
return resolvedComponents;
}
- resolvedComponents = new HashSet<>();
- Set<Bean<?>> deployedComponents = webBeansContext.getBeanManagerImpl().getBeans();
-
- //Finding all beans with given name
- for (Bean<?> component : deployedComponents)
+ // Once the bean set is final (post startup) the name index answers this directly. The scan
+ // below is O(all beans) per name, which validateBeanNames() repeats for every EL name in the
+ // deployment.
+ if (!startup)
+ {
+ Set<Bean<?>> named = getBeansByName().get(name);
+ // copied because the result is handed out and cached below
+ resolvedComponents = named == null ? new HashSet<>() : new HashSet<>(named);
+ }
+ else
{
- if (component.getName() != null)
+ resolvedComponents = new HashSet<>();
+ Set<Bean<?>> deployedComponents = webBeansContext.getBeanManagerImpl().getBeans();
+
+ //Finding all beans with given name
+ for (Bean<?> component : deployedComponents)
{
- if (component.getName().equals(name))
+ if (component.getName() != null)
{
- resolvedComponents.add(component);
+ if (component.getName().equals(name))
+ {
+ resolvedComponents.add(component);
+ }
}
}
}
@@ -466,11 +512,13 @@ public class InjectionResolver
boolean returnAll = injectionPointType.equals(Object.class) && currentQualifier;
+ // the raw type of the injection point is invariant across the whole scan below
+ Class<?> ipRawType = fastMatching ? ClassUtil.getRawPrimitiveType(injectionPointType) : null;
+
// Once the bean set is final (post startup) the fast-matching scan is a pure raw-type filter,
// so we can look up the candidate beans in the index instead of scanning the whole deployment.
if (fastMatching && !startup && !returnAll)
{
- Class<?> ipRawType = ClassUtil.getRawPrimitiveType(injectionPointType);
if (ipRawType != null)
{
Set<Bean<?>> candidates = getBeansByRawType().get(ipRawType);
@@ -505,13 +553,16 @@ public class InjectionResolver
{
if (fastMatching)
{
- for (Type componentApiType : component.getTypes())
+ if (ipRawType != null)
{
-
- if (ClassUtil.isRawClassEquals(injectionPointType, componentApiType))
+ for (Type componentApiType : component.getTypes())
{
- resolvedComponents.add(component);
- break;
+ Class<?> apiRawType = ClassUtil.getRawPrimitiveType(componentApiType);
+ if (apiRawType != null && ipRawType.equals(apiRawType))
+ {
+ resolvedComponents.add(component);
+ break;
+ }
}
}
}