Skip to content

Commit e6255b8

Browse files
authored
Merge pull request #752 from SentryMan/postConstructBeans
`PostConstruct` method Direct Injection
2 parents fa79dda + 65d9321 commit e6255b8

File tree

12 files changed

+205
-21
lines changed

12 files changed

+205
-21
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package org.example.myapp.config;
2+
3+
import io.avaje.inject.PostConstruct;
4+
import jakarta.inject.Named;
5+
import jakarta.inject.Singleton;
6+
7+
@Singleton
8+
public class LifeFour {
9+
10+
public String _state;
11+
12+
@PostConstruct
13+
void post(@Named("foo") LifeOne one, LifeTwo two) {
14+
_state = "post|"
15+
+ (one != null ? "one|" : "")
16+
+ (two != null ? "two" : "");
17+
}
18+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package org.example.myapp.config;
2+
3+
import io.avaje.inject.BeanScope;
4+
import io.avaje.inject.PostConstruct;
5+
import jakarta.inject.Singleton;
6+
7+
@Singleton
8+
public class LifeOne {
9+
10+
public String _state;
11+
12+
@PostConstruct
13+
void post(BeanScope scope) {
14+
_state = "post|"
15+
+ (scope != null ? "scope" : "");
16+
}
17+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package org.example.myapp.config;
2+
3+
import io.avaje.inject.BeanScope;
4+
import io.avaje.inject.PostConstruct;
5+
import io.avaje.inject.Prototype;
6+
7+
@Prototype
8+
public class LifeProtoTwo {
9+
10+
public String _state;
11+
12+
@PostConstruct
13+
void post(LifeOne one, BeanScope scope) {
14+
_state = "post|"
15+
+ (one != null ? "one|" : "")
16+
+ (scope != null ? "scope" : "");
17+
}
18+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package org.example.myapp.config;
2+
3+
import io.avaje.inject.PostConstruct;
4+
import jakarta.inject.Singleton;
5+
6+
@Singleton
7+
public class LifeThree {
8+
9+
public String _state;
10+
11+
@PostConstruct
12+
void post(LifeOne one) {
13+
_state = "post|"
14+
+ (one != null ? "one" : "");
15+
}
16+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package org.example.myapp.config;
2+
3+
import io.avaje.inject.BeanScope;
4+
import io.avaje.inject.PostConstruct;
5+
import jakarta.inject.Singleton;
6+
7+
@Singleton
8+
public class LifeTwo {
9+
10+
public String _state;
11+
12+
@PostConstruct
13+
void post(LifeOne one, BeanScope scope) {
14+
_state = "post|"
15+
+ (one != null ? "one|" : "")
16+
+ (scope != null ? "scope" : "");
17+
}
18+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package org.example.myapp.config;
2+
3+
import io.avaje.inject.BeanScope;
4+
import org.junit.jupiter.api.Test;
5+
6+
import static org.assertj.core.api.Assertions.assertThat;
7+
8+
class PostConstructParametersTest {
9+
10+
@Test
11+
void factorySecondaryAsProvider() {
12+
try (BeanScope testScope = BeanScope.builder().build()) {
13+
var one = testScope.get(LifeOne.class);
14+
var two = testScope.get(LifeTwo.class);
15+
var three = testScope.get(LifeThree.class);
16+
var four = testScope.get(LifeFour.class);
17+
var protoTwo = testScope.get(LifeProtoTwo.class);
18+
19+
assertThat(one._state).isEqualTo("post|scope");
20+
assertThat(two._state).isEqualTo("post|one|scope");
21+
assertThat(three._state).isEqualTo("post|one");
22+
assertThat(four._state).isEqualTo("post|one|two");
23+
assertThat(protoTwo._state).isEqualTo("post|one|scope");
24+
}
25+
}
26+
27+
}

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

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package io.avaje.inject.generator;
22

33
import static io.avaje.inject.generator.APContext.logError;
4-
54
import java.util.ArrayList;
65
import java.util.Collections;
76
import java.util.LinkedHashSet;
@@ -11,7 +10,6 @@
1110
import java.util.stream.Stream;
1211

1312
import javax.lang.model.element.Element;
14-
import javax.lang.model.element.ExecutableElement;
1513
import javax.lang.model.element.TypeElement;
1614
import javax.lang.model.type.TypeKind;
1715

@@ -30,7 +28,7 @@ final class BeanReader {
3028
private final List<MethodReader> injectMethods;
3129
private final List<MethodReader> factoryMethods;
3230
private final List<MethodReader> observerMethods;
33-
private final Element postConstructMethod;
31+
private final Optional<MethodReader> postConstructMethod;
3432
private final Element preDestroyMethod;
3533

3634
private final ImportTypeMap importTypes = new ImportTypeMap();
@@ -165,6 +163,8 @@ BeanReader read() {
165163
factoryMethod.addImports(importTypes);
166164
}
167165

166+
postConstructMethod.ifPresent(m -> m.addImports(importTypes));
167+
168168
conditions.addImports(importTypes);
169169
return this;
170170
}
@@ -242,6 +242,12 @@ Set<UType> allGenericTypes() {
242242
for (MethodReader factoryMethod : factoryMethods()) {
243243
factoryMethod.addDependsOnGeneric(allUTypes);
244244
}
245+
246+
postConstructMethod.ifPresent(m ->
247+
m.params().stream()
248+
.filter(MethodParam::isGenericParam)
249+
.map(MethodParam::getFullUType)
250+
.forEach(allUTypes::add));
245251
return allUTypes;
246252
}
247253

@@ -266,7 +272,7 @@ String metaKey() {
266272
* Return true if lifecycle via annotated methods is required.
267273
*/
268274
boolean hasLifecycleMethods() {
269-
return (postConstructMethod != null || preDestroyMethod != null || typeReader.isClosable());
275+
return (postConstructMethod.isPresent() || preDestroyMethod != null || typeReader.isClosable());
270276
}
271277

272278
List<MetaData> createFactoryMethodMeta() {
@@ -327,9 +333,10 @@ void buildRegister(Append writer) {
327333
}
328334

329335
void addLifecycleCallbacks(Append writer, String indent) {
330-
if (postConstructMethod != null && !registerProvider()) {
331-
writer.indent(indent).append(" builder.addPostConstruct($bean::%s);", postConstructMethod.getSimpleName()).eol();
336+
if (postConstructMethod.isPresent() && !registerProvider()) {
337+
writePostConstruct(writer, indent, postConstructMethod.get());
332338
}
339+
333340
if (preDestroyMethod != null) {
334341
lifeCycleNotSupported("@PreDestroy");
335342
var priority = preDestroyPriority == null || preDestroyPriority == 1000 ? "" : ", " + preDestroyPriority;
@@ -339,17 +346,46 @@ void addLifecycleCallbacks(Append writer, String indent) {
339346
}
340347
}
341348

349+
private void writePostConstruct(Append writer, String indent, MethodReader postConstruct) {
350+
writer.indent(indent).append(" builder.addPostConstruct(");
351+
final var methodName = postConstruct.name();
352+
final var params = postConstruct.params();
353+
if (params.isEmpty() || Constants.BEANSCOPE.equals(params.get(0).getFullUType().shortType())) {
354+
writer.append("$bean::%s);", methodName).eol();
355+
} else {
356+
writer.append("beanScope -> $bean.%s(", methodName);
357+
writeLifeCycleGet(writer, params, "beanScope", "beanScope");
358+
writer.append(");").eol();
359+
}
360+
}
361+
342362
void prototypePostConstruct(Append writer, String indent) {
343-
if (postConstructMethod != null) {
344-
var postConstruct = (ExecutableElement) postConstructMethod;
345-
writer.indent(indent).append(" bean.%s(", postConstructMethod.getSimpleName());
346-
if (postConstruct.getParameters().isEmpty()) {
363+
postConstructMethod.ifPresent(m -> {
364+
writer.indent(indent).append(" bean.%s(", m.name());
365+
if (m.params().isEmpty()) {
347366
writer.append(");").eol();
348367
} else {
349-
writer.append("builder.get(io.avaje.inject.BeanScope.class));").eol();
368+
writeLifeCycleGet(writer, m.params(), "builder", "builder.get(io.avaje.inject.BeanScope.class)");
369+
writer.append(";").eol();
350370
}
351371
writer.eol();
372+
});
373+
}
374+
375+
private void writeLifeCycleGet(Append writer, List<MethodParam> params, String builderName, String beanScopeString) {
376+
final var size = params.size();
377+
for (int i = 0; i < size; i++) {
378+
if (i > 0) {
379+
writer.append(", ");
380+
}
381+
final var param = params.get(i);
382+
if (Constants.BEANSCOPE.equals(param.getFullUType().fullWithoutAnnotations())) {
383+
writer.append(beanScopeString);
384+
} else {
385+
param.builderGetDependency(writer, builderName);
386+
}
352387
}
388+
writer.append(")");
353389
}
354390

355391
private void lifeCycleNotSupported(String lifecycle) {

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ final class TypeExtendsInjection {
3030
private final TypeElement baseType;
3131
private final boolean factory;
3232
private final List<AspectPair> typeAspects;
33-
private Element postConstructMethod;
33+
private Optional<MethodReader> postConstructMethod = Optional.empty();
3434
private Element preDestroyMethod;
3535
private Integer preDestroyPriority;
3636

@@ -125,7 +125,7 @@ private void readMethod(Element element, TypeElement type) {
125125
notInjectMethods.add(methodKey);
126126
}
127127
if (AnnotationUtil.hasAnnotationWithName(element, "PostConstruct")) {
128-
postConstructMethod = element;
128+
postConstructMethod = Optional.of(new MethodReader(methodElement, type, importTypes).read());
129129
checkAspect = false;
130130
}
131131
if (AnnotationUtil.hasAnnotationWithName(element, "PreDestroy")) {
@@ -206,7 +206,7 @@ List<MethodReader> observerMethods() {
206206
return observerMethods;
207207
}
208208

209-
Element postConstructMethod() {
209+
Optional<MethodReader> postConstructMethod() {
210210
return postConstructMethod;
211211
}
212212

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import java.util.ArrayList;
88
import java.util.List;
99
import java.util.Objects;
10+
import java.util.Optional;
1011
import java.util.Set;
1112
import java.util.stream.Collectors;
1213
import java.util.stream.Stream;
@@ -101,7 +102,7 @@ List<MethodReader> observerMethods() {
101102
return extendsInjection.observerMethods();
102103
}
103104

104-
Element postConstructMethod() {
105+
Optional<MethodReader> postConstructMethod() {
105106
return extendsInjection.postConstructMethod();
106107
}
107108

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
package io.avaje.inject.generator;
22

3-
import javax.lang.model.element.Element;
4-
import javax.lang.model.element.TypeElement;
5-
import javax.lang.model.type.TypeKind;
6-
import javax.lang.model.type.TypeMirror;
3+
import static java.util.stream.Collectors.toList;
74

85
import java.util.List;
96
import java.util.Optional;
107
import java.util.Set;
11-
import static java.util.stream.Collectors.toList;
8+
9+
import javax.lang.model.element.Element;
10+
import javax.lang.model.element.TypeElement;
11+
import javax.lang.model.type.TypeKind;
1212

1313
final class TypeReader {
1414

@@ -107,7 +107,7 @@ List<MethodReader> observerMethods() {
107107
return extendsReader.observerMethods();
108108
}
109109

110-
Element postConstructMethod() {
110+
Optional<MethodReader> postConstructMethod() {
111111
return extendsReader.postConstructMethod();
112112
}
113113

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package io.avaje.inject.generator.models.valid.lifecycle;
2+
3+
import java.util.function.Consumer;
4+
5+
import io.avaje.inject.BeanScope;
6+
import io.avaje.inject.PostConstruct;
7+
import jakarta.inject.Singleton;
8+
9+
@Singleton
10+
public class Minos {
11+
12+
@PostConstruct
13+
void prepareThyself(Serpent serpent, Consumer<String> c, BeanScope b) {}
14+
15+
// @PreDestroy
16+
// void thyEndIsNow() {
17+
// }
18+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package io.avaje.inject.generator.models.valid.lifecycle;
2+
3+
import java.util.function.Consumer;
4+
5+
import io.avaje.inject.BeanScope;
6+
import io.avaje.inject.PostConstruct;
7+
import io.avaje.inject.Prototype;
8+
9+
@Prototype
10+
public class Serpent {
11+
12+
@PostConstruct
13+
void hiss(Consumer<String> c, BeanScope b) {}
14+
15+
}

0 commit comments

Comments
 (0)