Skip to content

Commit 059d4ad

Browse files
committed
#235 - Support injecting BeanScope
1 parent 91baed8 commit 059d4ad

File tree

5 files changed

+170
-8
lines changed

5 files changed

+170
-8
lines changed

inject-generator/src/main/java/io/avaje/inject/generator/BeanReader.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,11 @@ List<Dependency> getDependsOn() {
9797
List<Dependency> list = new ArrayList<>();
9898
if (constructor != null) {
9999
for (MethodReader.MethodParam param : constructor.getParams()) {
100-
list.add(param.getDependsOn());
100+
Dependency dependsOn = param.getDependsOn();
101+
// BeanScope is always injectable with no impact on injection ordering
102+
if (!dependsOn.dependsOn().equals(Constants.BEANSCOPE)) {
103+
list.add(dependsOn);
104+
}
101105
}
102106
}
103107
return list;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package org.example.coffee;
2+
3+
import io.avaje.inject.BeanScope;
4+
import io.avaje.inject.Component;
5+
import org.example.optional.Que;
6+
7+
/**
8+
* Depends on the BeanScope.
9+
*/
10+
@Component
11+
class INeedBeanScope {
12+
13+
final BeanScope beanScope;
14+
15+
INeedBeanScope(BeanScope beanScope) {
16+
this.beanScope = beanScope;
17+
}
18+
19+
Que getQueue() {
20+
return beanScope.get(Que.class, "frodo");
21+
}
22+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package org.example.coffee;
2+
3+
import io.avaje.inject.BeanScope;
4+
import org.example.optional.Que;
5+
import org.junit.jupiter.api.Test;
6+
7+
import static org.assertj.core.api.Assertions.assertThat;
8+
9+
/**
10+
* Test that we can inject BeanScope.
11+
*/
12+
class InjectBeanScopeTest {
13+
14+
@Test
15+
void test() {
16+
try (BeanScope beanScope = BeanScope.builder().build()) {
17+
INeedBeanScope need = beanScope.get(INeedBeanScope.class);
18+
Que queue = need.getQueue();
19+
20+
String result = queue.push("hi");
21+
assertThat(result).isEqualTo("hi|frodo");
22+
}
23+
}
24+
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package io.avaje.inject.spi;
2+
3+
import io.avaje.inject.BeanEntry;
4+
import io.avaje.inject.BeanScope;
5+
6+
import java.lang.annotation.Annotation;
7+
import java.lang.reflect.Type;
8+
import java.util.List;
9+
import java.util.Map;
10+
import java.util.Optional;
11+
12+
/**
13+
* Proxy used when injecting the BeanScope.
14+
*/
15+
class DBeanScopeProxy implements BeanScope {
16+
17+
private BeanScope delegate;
18+
19+
/**
20+
* This happens just before the BeanScope is started.
21+
*
22+
* @param delegate The actual BeanScope
23+
*/
24+
void inject(BeanScope delegate) {
25+
this.delegate = delegate;
26+
}
27+
28+
@Override
29+
public <T> T get(Class<T> type) {
30+
return delegate.get(type);
31+
}
32+
33+
@Override
34+
public <T> T get(Class<T> type, String name) {
35+
return delegate.get(type, name);
36+
}
37+
38+
@Override
39+
public <T> T get(Type type, String name) {
40+
return delegate.get(type, name);
41+
}
42+
43+
@Override
44+
public <T> Optional<T> getOptional(Class<T> type) {
45+
return delegate.getOptional(type);
46+
}
47+
48+
@Override
49+
public <T> Optional<T> getOptional(Type type, String name) {
50+
return delegate.getOptional(type, name);
51+
}
52+
53+
@Override
54+
public List<Object> listByAnnotation(Class<?> annotation) {
55+
return delegate.listByAnnotation(annotation);
56+
}
57+
58+
@Override
59+
public <T> List<T> list(Class<T> type) {
60+
return delegate.list(type);
61+
}
62+
63+
@Override
64+
public <T> List<T> list(Type type) {
65+
return delegate.list(type);
66+
}
67+
68+
@Override
69+
public <T> List<T> listByPriority(Class<T> type) {
70+
return delegate.listByPriority(type);
71+
}
72+
73+
@Override
74+
public <T> List<T> listByPriority(Class<T> type, Class<? extends Annotation> priority) {
75+
return delegate.listByPriority(type, priority);
76+
}
77+
78+
@Override
79+
public <T> Map<String, T> map(Type type) {
80+
return delegate.map(type);
81+
}
82+
83+
@Override
84+
public List<BeanEntry> all() {
85+
return delegate.all();
86+
}
87+
88+
@Override
89+
public boolean contains(Type type) {
90+
return delegate.contains(type);
91+
}
92+
93+
@Override
94+
public boolean contains(String type) {
95+
return delegate.contains(type);
96+
}
97+
98+
@Override
99+
public void close() {
100+
delegate.close();
101+
}
102+
}

inject/src/main/java/io/avaje/inject/spi/DBuilder.java

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,34 +17,29 @@ class DBuilder implements Builder {
1717
*/
1818
private final List<Runnable> postConstruct = new ArrayList<>();
1919
private final List<AutoCloseable> preDestroy = new ArrayList<>();
20-
2120
/**
2221
* List of field injection closures.
2322
*/
2423
private final List<Consumer<Builder>> injectors = new ArrayList<>();
25-
2624
/**
2725
* The beans created and added to the scope during building.
2826
*/
2927
protected final DBeanMap beanMap = new DBeanMap();
30-
3128
protected final BeanScope parent;
3229
protected final boolean parentOverride;
33-
3430
/**
3531
* Bean provided by the parent scope that we are not overriding.
3632
*/
3733
protected Object parentMatch;
38-
3934
/**
4035
* Debug of the current bean being wired - used in injection errors.
4136
*/
4237
private Type injectTarget;
43-
4438
/**
4539
* Flag set when we are running post construct injection.
4640
*/
4741
private boolean runningPostConstruct;
42+
private DBeanScopeProxy beanScopeProxy;
4843

4944
DBuilder(BeanScope parent, boolean parentOverride) {
5045
this.parent = parent;
@@ -253,13 +248,24 @@ public <T> T get(Type cls) {
253248

254249
@Override
255250
public <T> T get(Type cls, String name) {
251+
if (BeanScope.class.equals(cls)) {
252+
return injectBeanScope();
253+
}
256254
T bean = getMaybe(cls, name);
257255
if (bean == null) {
258256
throw new IllegalStateException(errorInjectingNull(cls, name));
259257
}
260258
return bean;
261259
}
262260

261+
@SuppressWarnings("unchecked")
262+
private <T> T injectBeanScope() {
263+
if (beanScopeProxy == null) {
264+
beanScopeProxy = new DBeanScopeProxy();
265+
}
266+
return (T) beanScopeProxy;
267+
}
268+
263269
private <T> String errorInjectingNull(Type cls, String name) {
264270
String msg = "Injecting null for " + cls.getTypeName();
265271
if (name != null) {
@@ -284,6 +290,10 @@ private void runInjectors() {
284290

285291
public BeanScope build(boolean withShutdownHook) {
286292
runInjectors();
287-
return new DBeanScope(withShutdownHook, preDestroy, postConstruct, beanMap, parent).start();
293+
var scope = new DBeanScope(withShutdownHook, preDestroy, postConstruct, beanMap, parent);
294+
if (beanScopeProxy != null) {
295+
beanScopeProxy.inject(scope);
296+
}
297+
return scope.start();
288298
}
289299
}

0 commit comments

Comments
 (0)