From e92f0b9f604f8571fda0c4bff53befc8ce745f5f Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Tue, 9 Dec 2025 22:14:57 -0500 Subject: [PATCH 1/3] Make `isBeanAbsent` not count secondary beans Secondary beans should not be wired under any circumstance if there are alternatives --- .../java/io/avaje/inject/spi/DBeanMap.java | 11 ++++---- .../java/io/avaje/inject/spi/DBeanScope.java | 24 ++++++++---------- .../java/io/avaje/inject/spi/DBuilder.java | 4 +-- .../io/avaje/inject/spi/DContextEntry.java | 25 ++++++++++--------- 4 files changed, 30 insertions(+), 34 deletions(-) diff --git a/inject/src/main/java/io/avaje/inject/spi/DBeanMap.java b/inject/src/main/java/io/avaje/inject/spi/DBeanMap.java index 229b00eb..06a9ef6b 100644 --- a/inject/src/main/java/io/avaje/inject/spi/DBeanMap.java +++ b/inject/src/main/java/io/avaje/inject/spi/DBeanMap.java @@ -102,15 +102,13 @@ void register(Provider provider) { } } - /** - * Get with a strict match on name for the single entry case. - */ - Object getStrict(Type type, String name) { + /** Check if a non secondary entry exists */ + Object nonDefaultEntry(Type type, String name) { DContextEntry entry = beans.get(type.getTypeName()); if (entry == null) { return null; } - return entry.getStrict(name); + return entry.nonDefaultEntry(name); } boolean contains(String type) { @@ -175,7 +173,8 @@ Map map(Type type, BeanScope parent) { Map localMap = map(type); if (parentMap.isEmpty()) { return localMap; - } else if (localMap.isEmpty()) { + } + if (localMap.isEmpty()) { return parentMap; } Map result = new LinkedHashMap<>(parentMap); diff --git a/inject/src/main/java/io/avaje/inject/spi/DBeanScope.java b/inject/src/main/java/io/avaje/inject/spi/DBeanScope.java index c760c1d1..05495c2b 100644 --- a/inject/src/main/java/io/avaje/inject/spi/DBeanScope.java +++ b/inject/src/main/java/io/avaje/inject/spi/DBeanScope.java @@ -111,20 +111,17 @@ private T getByType(Type type, @Nullable String name) { return parent.get(type, name); } - /** - * Get with a strict match on name for the single entry case. - */ - @Nullable - Object getStrict(@Nullable String name, Type[] types) { + /** Check if a non secondary entry exists */ + Object nonDefaultEntry(@Nullable String name, Type[] types) { for (Type type : types) { - Object match = beans.getStrict(type, name); + var match = beans.nonDefaultEntry(type, name); if (match != null) { return match; } } if (parent instanceof DBeanScope) { DBeanScope dParent = (DBeanScope) parent; - return dParent.getStrict(name, types); + return dParent.nonDefaultEntry(name, types); } return null; } @@ -181,14 +178,14 @@ private List listOf(Type type, @Nullable String name) { } static List combine(List values, List parentValues) { - if (values.isEmpty()) { + if (values.isEmpty()){ return parentValues; - } else if (parentValues.isEmpty()) { - return values; - } else { - values.addAll(parentValues); + } + if (parentValues.isEmpty()){ return values; } + values.addAll(parentValues); + return values; } @Override @@ -266,8 +263,7 @@ private void shutdown() { @Override public Set customScopeAnnotations() { if (parent != null) { - final Set scopes = new HashSet<>(); - scopes.addAll(beans.scopeAnnotations()); + final Set scopes = new HashSet<>(beans.scopeAnnotations()); scopes.addAll(parent.customScopeAnnotations()); return scopes; } diff --git a/inject/src/main/java/io/avaje/inject/spi/DBuilder.java b/inject/src/main/java/io/avaje/inject/spi/DBuilder.java index 160c2f00..76aef525 100644 --- a/inject/src/main/java/io/avaje/inject/spi/DBuilder.java +++ b/inject/src/main/java/io/avaje/inject/spi/DBuilder.java @@ -77,9 +77,9 @@ public boolean isBeanAbsent(@Nullable String name, Type... types) { return true; } if (parent instanceof DBeanScope) { - // effectively looking for a match in the parent scope + // look for a match in the parent scope final DBeanScope dParent = (DBeanScope) parent; - parentMatch = dParent.getStrict(name, removeAnnotations(types)); + parentMatch = dParent.nonDefaultEntry(name, removeAnnotations(types)); return parentMatch == null; } return true; diff --git a/inject/src/main/java/io/avaje/inject/spi/DContextEntry.java b/inject/src/main/java/io/avaje/inject/spi/DContextEntry.java index 518537f1..f15124d7 100644 --- a/inject/src/main/java/io/avaje/inject/spi/DContextEntry.java +++ b/inject/src/main/java/io/avaje/inject/spi/DContextEntry.java @@ -38,14 +38,18 @@ Provider provider(String name, Class currentModule) { return new EntryMatcher(name, currentModule).provider(entries); } - /** - * Get with strict name match for the single entry case. - */ - Object getStrict(String name) { + /** Check if a non secondary entry exists */ + Object nonDefaultEntry(String name) { + DContextEntryBean entry; if (entries.size() == 1) { - return entries.get(0).beanIfNameMatch(name); + entry = entries.get(0); + return entry.isNameMatch(name) && entry.priority() != BeanEntry.SECONDARY + ? entry.bean() + : null; } - return new EntryMatcher(name, null).match(entries); + entry = new EntryMatcher(name, null).findMatch(entries); + + return entry != null && entry.priority() != BeanEntry.SECONDARY ? entry.bean() : null; } Object get(String name, Class currentModule) { @@ -156,7 +160,8 @@ private void checkMatch(DContextEntryBean entry) { if (match.priority() < entry.priority()) { // existing supplied match always wins return; - } else if (match.priority() > entry.priority()) { + } + if (match.priority() > entry.priority()) { // new supplied wins match = entry; return; @@ -171,13 +176,9 @@ private void checkMatch(DContextEntryBean entry) { } // leave as is, current primary wins return; - } else if (impliedName) { - ignoredSecondaryMatch = entry; - return; } - // try to resolve match using qualifier name (including null) - if (match.isNameEqual(name) && !entry.isNameEqual(name)) { + if (impliedName || (match.isNameEqual(name) && !entry.isNameEqual(name))) { ignoredSecondaryMatch = entry; return; } else if (!match.isNameEqual(name) && entry.isNameEqual(name)) { From c71b43c48896282009d356ac39ee06931a2ff325 Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Wed, 10 Dec 2025 00:28:50 -0500 Subject: [PATCH 2/3] Add nonDefaultEntry method to DBeanScope --- inject/src/main/java/io/avaje/inject/spi/DBeanScope.java | 1 + 1 file changed, 1 insertion(+) diff --git a/inject/src/main/java/io/avaje/inject/spi/DBeanScope.java b/inject/src/main/java/io/avaje/inject/spi/DBeanScope.java index 05495c2b..cb97e2da 100644 --- a/inject/src/main/java/io/avaje/inject/spi/DBeanScope.java +++ b/inject/src/main/java/io/avaje/inject/spi/DBeanScope.java @@ -112,6 +112,7 @@ private T getByType(Type type, @Nullable String name) { } /** Check if a non secondary entry exists */ + @Nullable Object nonDefaultEntry(@Nullable String name, Type[] types) { for (Type type : types) { var match = beans.nonDefaultEntry(type, name); From 42a4e94be5363feea499543b48be8155f4ca7fac Mon Sep 17 00:00:00 2001 From: Rob Bygrave Date: Wed, 10 Dec 2025 19:25:18 +1300 Subject: [PATCH 3/3] Add DContextEntryBean.nonDefaultMatch() method --- .../src/main/java/io/avaje/inject/spi/DBeanScope.java | 4 ++-- .../main/java/io/avaje/inject/spi/DContextEntry.java | 11 +++-------- .../java/io/avaje/inject/spi/DContextEntryBean.java | 4 ++++ 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/inject/src/main/java/io/avaje/inject/spi/DBeanScope.java b/inject/src/main/java/io/avaje/inject/spi/DBeanScope.java index cb97e2da..89923114 100644 --- a/inject/src/main/java/io/avaje/inject/spi/DBeanScope.java +++ b/inject/src/main/java/io/avaje/inject/spi/DBeanScope.java @@ -179,10 +179,10 @@ private List listOf(Type type, @Nullable String name) { } static List combine(List values, List parentValues) { - if (values.isEmpty()){ + if (values.isEmpty()) { return parentValues; } - if (parentValues.isEmpty()){ + if (parentValues.isEmpty()) { return values; } values.addAll(parentValues); diff --git a/inject/src/main/java/io/avaje/inject/spi/DContextEntry.java b/inject/src/main/java/io/avaje/inject/spi/DContextEntry.java index f15124d7..abb0d2b7 100644 --- a/inject/src/main/java/io/avaje/inject/spi/DContextEntry.java +++ b/inject/src/main/java/io/avaje/inject/spi/DContextEntry.java @@ -40,16 +40,11 @@ Provider provider(String name, Class currentModule) { /** Check if a non secondary entry exists */ Object nonDefaultEntry(String name) { - DContextEntryBean entry; if (entries.size() == 1) { - entry = entries.get(0); - return entry.isNameMatch(name) && entry.priority() != BeanEntry.SECONDARY - ? entry.bean() - : null; + return entries.get(0).nonDefaultMatch(name); } - entry = new EntryMatcher(name, null).findMatch(entries); - - return entry != null && entry.priority() != BeanEntry.SECONDARY ? entry.bean() : null; + var entry = new EntryMatcher(name, null).findMatch(entries); + return entry != null ? entry.nonDefaultMatch(null) : null; } Object get(String name, Class currentModule) { diff --git a/inject/src/main/java/io/avaje/inject/spi/DContextEntryBean.java b/inject/src/main/java/io/avaje/inject/spi/DContextEntryBean.java index 8fdf1e99..c4caa25a 100644 --- a/inject/src/main/java/io/avaje/inject/spi/DContextEntryBean.java +++ b/inject/src/main/java/io/avaje/inject/spi/DContextEntryBean.java @@ -109,6 +109,10 @@ final boolean isSupplied(String qualifierName) { return priority == BeanEntry.SUPPLIED && (qualifierName == null || qualifierName.equals(name)); } + final Object nonDefaultMatch(String name) { + return isNameMatch(name) && priority != BeanEntry.SECONDARY ? bean() : null; + } + /** * Prototype scope Provider based entry. */