Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,13 @@ public <Q> Supplier<Q> doGetCompiledBinding(Dependency<Q> dep) {
if (key.getRawType() == List.class) {
Set<Binding<Object>> res2 = getBindings(key.getTypeParameter(0));
if (res2 != null) {
List<Supplier<Object>> list = res2.stream().map(this::compile).collect(Collectors.toList());
// Sort bindings by priority (highest first) for deterministic ordering
List<Binding<Object>> sortedBindings = new ArrayList<>(res2);
Comparator<Binding<Object>> comparing = Comparator.comparing(Binding::getPriority);
sortedBindings.sort(comparing.reversed());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
sortedBindings.sort(comparing.reversed());
sortedBindings.sort(Binding.getPriorityComparator());

could shift feature envy in dedicated domain Binding.

public Comparator<Binding<Object>> getPriorityComparator() {
    return Comparator.comparing(Binding::getPriority);
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might do this, as leaner than implementing comparable. Both better then this to avoid exact this situation:

image

DRY DRY DRY


List<Supplier<Object>> list =
sortedBindings.stream().map(this::compile).collect(Collectors.toList());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

List<Binding<Object>> sortedBindings = new ArrayList<>(res2);
sortedBindings.sort(Comparator.reverseOrder());
//noinspection unchecked
return () -> (Q) list(sortedBindings.stream().map(this::compile).collect(Collectors.toList()), Supplier::get);
    @Override
    public int compareTo(Binding<Object> objectBinding) {
        return Integer.compare(this.priority, objectBinding.priority);
    }

//noinspection unchecked
return () -> (Q) list(list, Supplier::get);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

considering this domain logic, might use OOP implementing comparable as its wont hurt nobody giving special attention and cohesion to core logic.

image

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,20 @@ void injectListTest() {
assertNotSame(services.get(0).getClass(), services.get(1).getClass());
}

@Test
void injectListWithPriorityTest() {
Injector injector = Injector.create().bindImplicit(InjectListWithPriority.class);
List<InjectListWithPriority.MyService> services =
injector.getInstance(new Key<List<InjectListWithPriority.MyService>>() {});
assertNotNull(services);
assertEquals(3, services.size());

// Verify services are ordered by priority (highest first)
assertInstanceOf(InjectListWithPriority.HighPriorityServiceImpl.class, services.get(0));
assertInstanceOf(InjectListWithPriority.MediumPriorityServiceImpl.class, services.get(1));
assertInstanceOf(InjectListWithPriority.LowPriorityServiceImpl.class, services.get(2));
}

static class InjectList {

interface MyService {}
Expand All @@ -213,6 +227,23 @@ static class MyServiceImpl implements MyService {}
static class AnotherServiceImpl implements MyService {}
}

static class InjectListWithPriority {

interface MyService {}

@Named
@Priority(100)
static class HighPriorityServiceImpl implements MyService {}

@Named
@Priority(50)
static class MediumPriorityServiceImpl implements MyService {}

@Named
@Priority(10)
static class LowPriorityServiceImpl implements MyService {}
}

@Test
void injectMapTest() {
Injector injector = Injector.create().bindImplicit(InjectMap.class);
Expand Down Expand Up @@ -392,6 +423,25 @@ void testCircularPriorityDependency() {
.hasMessageContaining("MyService");
}

@Test
void testListInjectionWithMixedPriorities() {
Injector injector = Injector.create().bindImplicit(MixedPriorityTest.class);
List<MixedPriorityTest.MyService> services =
injector.getInstance(new Key<List<MixedPriorityTest.MyService>>() {});
assertNotNull(services);
assertEquals(4, services.size());

// Verify services are ordered by priority (highest first)
// Priority 200 (highest)
assertInstanceOf(MixedPriorityTest.VeryHighPriorityServiceImpl.class, services.get(0));
// Priority 100
assertInstanceOf(MixedPriorityTest.HighPriorityServiceImpl.class, services.get(1));
// Priority 50
assertInstanceOf(MixedPriorityTest.MediumPriorityServiceImpl.class, services.get(2));
// No priority annotation (default 0)
assertInstanceOf(MixedPriorityTest.DefaultPriorityServiceImpl.class, services.get(3));
}

static class CircularPriorityTest {
interface MyService {}

Expand All @@ -405,4 +455,24 @@ static class HighPriorityServiceImpl implements MyService {
MyService defaultService; // This tries to inject the default implementation
}
}

static class MixedPriorityTest {

interface MyService {}

@Named
@Priority(200)
static class VeryHighPriorityServiceImpl implements MyService {}

@Named
@Priority(100)
static class HighPriorityServiceImpl implements MyService {}

@Named
@Priority(50)
static class MediumPriorityServiceImpl implements MyService {}

@Named
static class DefaultPriorityServiceImpl implements MyService {}
}
}