Skip to content

Commit

Permalink
Merge pull request #752 from SentryMan/postConstructBeans
Browse files Browse the repository at this point in the history
`PostConstruct` method Direct Injection
  • Loading branch information
SentryMan authored Jan 6, 2025
2 parents fa79dda + 65d9321 commit e6255b8
Show file tree
Hide file tree
Showing 12 changed files with 205 additions and 21 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.example.myapp.config;

import io.avaje.inject.PostConstruct;
import jakarta.inject.Named;
import jakarta.inject.Singleton;

@Singleton
public class LifeFour {

public String _state;

@PostConstruct
void post(@Named("foo") LifeOne one, LifeTwo two) {
_state = "post|"
+ (one != null ? "one|" : "")
+ (two != null ? "two" : "");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.example.myapp.config;

import io.avaje.inject.BeanScope;
import io.avaje.inject.PostConstruct;
import jakarta.inject.Singleton;

@Singleton
public class LifeOne {

public String _state;

@PostConstruct
void post(BeanScope scope) {
_state = "post|"
+ (scope != null ? "scope" : "");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.example.myapp.config;

import io.avaje.inject.BeanScope;
import io.avaje.inject.PostConstruct;
import io.avaje.inject.Prototype;

@Prototype
public class LifeProtoTwo {

public String _state;

@PostConstruct
void post(LifeOne one, BeanScope scope) {
_state = "post|"
+ (one != null ? "one|" : "")
+ (scope != null ? "scope" : "");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.example.myapp.config;

import io.avaje.inject.PostConstruct;
import jakarta.inject.Singleton;

@Singleton
public class LifeThree {

public String _state;

@PostConstruct
void post(LifeOne one) {
_state = "post|"
+ (one != null ? "one" : "");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.example.myapp.config;

import io.avaje.inject.BeanScope;
import io.avaje.inject.PostConstruct;
import jakarta.inject.Singleton;

@Singleton
public class LifeTwo {

public String _state;

@PostConstruct
void post(LifeOne one, BeanScope scope) {
_state = "post|"
+ (one != null ? "one|" : "")
+ (scope != null ? "scope" : "");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package org.example.myapp.config;

import io.avaje.inject.BeanScope;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

class PostConstructParametersTest {

@Test
void factorySecondaryAsProvider() {
try (BeanScope testScope = BeanScope.builder().build()) {
var one = testScope.get(LifeOne.class);
var two = testScope.get(LifeTwo.class);
var three = testScope.get(LifeThree.class);
var four = testScope.get(LifeFour.class);
var protoTwo = testScope.get(LifeProtoTwo.class);

assertThat(one._state).isEqualTo("post|scope");
assertThat(two._state).isEqualTo("post|one|scope");
assertThat(three._state).isEqualTo("post|one");
assertThat(four._state).isEqualTo("post|one|two");
assertThat(protoTwo._state).isEqualTo("post|one|scope");
}
}

}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package io.avaje.inject.generator;

import static io.avaje.inject.generator.APContext.logError;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
Expand All @@ -11,7 +10,6 @@
import java.util.stream.Stream;

import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeKind;

Expand All @@ -30,7 +28,7 @@ final class BeanReader {
private final List<MethodReader> injectMethods;
private final List<MethodReader> factoryMethods;
private final List<MethodReader> observerMethods;
private final Element postConstructMethod;
private final Optional<MethodReader> postConstructMethod;
private final Element preDestroyMethod;

private final ImportTypeMap importTypes = new ImportTypeMap();
Expand Down Expand Up @@ -165,6 +163,8 @@ BeanReader read() {
factoryMethod.addImports(importTypes);
}

postConstructMethod.ifPresent(m -> m.addImports(importTypes));

conditions.addImports(importTypes);
return this;
}
Expand Down Expand Up @@ -242,6 +242,12 @@ Set<UType> allGenericTypes() {
for (MethodReader factoryMethod : factoryMethods()) {
factoryMethod.addDependsOnGeneric(allUTypes);
}

postConstructMethod.ifPresent(m ->
m.params().stream()
.filter(MethodParam::isGenericParam)
.map(MethodParam::getFullUType)
.forEach(allUTypes::add));
return allUTypes;
}

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

List<MetaData> createFactoryMethodMeta() {
Expand Down Expand Up @@ -327,9 +333,10 @@ void buildRegister(Append writer) {
}

void addLifecycleCallbacks(Append writer, String indent) {
if (postConstructMethod != null && !registerProvider()) {
writer.indent(indent).append(" builder.addPostConstruct($bean::%s);", postConstructMethod.getSimpleName()).eol();
if (postConstructMethod.isPresent() && !registerProvider()) {
writePostConstruct(writer, indent, postConstructMethod.get());
}

if (preDestroyMethod != null) {
lifeCycleNotSupported("@PreDestroy");
var priority = preDestroyPriority == null || preDestroyPriority == 1000 ? "" : ", " + preDestroyPriority;
Expand All @@ -339,17 +346,46 @@ void addLifecycleCallbacks(Append writer, String indent) {
}
}

private void writePostConstruct(Append writer, String indent, MethodReader postConstruct) {
writer.indent(indent).append(" builder.addPostConstruct(");
final var methodName = postConstruct.name();
final var params = postConstruct.params();
if (params.isEmpty() || Constants.BEANSCOPE.equals(params.get(0).getFullUType().shortType())) {
writer.append("$bean::%s);", methodName).eol();
} else {
writer.append("beanScope -> $bean.%s(", methodName);
writeLifeCycleGet(writer, params, "beanScope", "beanScope");
writer.append(");").eol();
}
}

void prototypePostConstruct(Append writer, String indent) {
if (postConstructMethod != null) {
var postConstruct = (ExecutableElement) postConstructMethod;
writer.indent(indent).append(" bean.%s(", postConstructMethod.getSimpleName());
if (postConstruct.getParameters().isEmpty()) {
postConstructMethod.ifPresent(m -> {
writer.indent(indent).append(" bean.%s(", m.name());
if (m.params().isEmpty()) {
writer.append(");").eol();
} else {
writer.append("builder.get(io.avaje.inject.BeanScope.class));").eol();
writeLifeCycleGet(writer, m.params(), "builder", "builder.get(io.avaje.inject.BeanScope.class)");
writer.append(";").eol();
}
writer.eol();
});
}

private void writeLifeCycleGet(Append writer, List<MethodParam> params, String builderName, String beanScopeString) {
final var size = params.size();
for (int i = 0; i < size; i++) {
if (i > 0) {
writer.append(", ");
}
final var param = params.get(i);
if (Constants.BEANSCOPE.equals(param.getFullUType().fullWithoutAnnotations())) {
writer.append(beanScopeString);
} else {
param.builderGetDependency(writer, builderName);
}
}
writer.append(")");
}

private void lifeCycleNotSupported(String lifecycle) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ final class TypeExtendsInjection {
private final TypeElement baseType;
private final boolean factory;
private final List<AspectPair> typeAspects;
private Element postConstructMethod;
private Optional<MethodReader> postConstructMethod = Optional.empty();
private Element preDestroyMethod;
private Integer preDestroyPriority;

Expand Down Expand Up @@ -125,7 +125,7 @@ private void readMethod(Element element, TypeElement type) {
notInjectMethods.add(methodKey);
}
if (AnnotationUtil.hasAnnotationWithName(element, "PostConstruct")) {
postConstructMethod = element;
postConstructMethod = Optional.of(new MethodReader(methodElement, type, importTypes).read());
checkAspect = false;
}
if (AnnotationUtil.hasAnnotationWithName(element, "PreDestroy")) {
Expand Down Expand Up @@ -206,7 +206,7 @@ List<MethodReader> observerMethods() {
return observerMethods;
}

Element postConstructMethod() {
Optional<MethodReader> postConstructMethod() {
return postConstructMethod;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
Expand Down Expand Up @@ -101,7 +102,7 @@ List<MethodReader> observerMethods() {
return extendsInjection.observerMethods();
}

Element postConstructMethod() {
Optional<MethodReader> postConstructMethod() {
return extendsInjection.postConstructMethod();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package io.avaje.inject.generator;

import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import static java.util.stream.Collectors.toList;

import java.util.List;
import java.util.Optional;
import java.util.Set;
import static java.util.stream.Collectors.toList;

import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeKind;

final class TypeReader {

Expand Down Expand Up @@ -107,7 +107,7 @@ List<MethodReader> observerMethods() {
return extendsReader.observerMethods();
}

Element postConstructMethod() {
Optional<MethodReader> postConstructMethod() {
return extendsReader.postConstructMethod();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package io.avaje.inject.generator.models.valid.lifecycle;

import java.util.function.Consumer;

import io.avaje.inject.BeanScope;
import io.avaje.inject.PostConstruct;
import jakarta.inject.Singleton;

@Singleton
public class Minos {

@PostConstruct
void prepareThyself(Serpent serpent, Consumer<String> c, BeanScope b) {}

// @PreDestroy
// void thyEndIsNow() {
// }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package io.avaje.inject.generator.models.valid.lifecycle;

import java.util.function.Consumer;

import io.avaje.inject.BeanScope;
import io.avaje.inject.PostConstruct;
import io.avaje.inject.Prototype;

@Prototype
public class Serpent {

@PostConstruct
void hiss(Consumer<String> c, BeanScope b) {}

}

0 comments on commit e6255b8

Please sign in to comment.