Skip to content

Commit e7df0e4

Browse files
committed
Aspect support - add providesAspect() to meta data
- Aspects provides/requires working with the annotation only - Fix a service loading catching expected exception
1 parent 77f5859 commit e7df0e4

File tree

20 files changed

+233
-115
lines changed

20 files changed

+233
-115
lines changed

blackbox-aspect/pom.xml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<parent>
6+
<artifactId>avaje-inject-parent</artifactId>
7+
<groupId>io.avaje</groupId>
8+
<version>8.11</version>
9+
</parent>
10+
<modelVersion>4.0.0</modelVersion>
11+
12+
<artifactId>blackbox-aspect</artifactId>
13+
14+
<properties>
15+
<maven.compiler.source>17</maven.compiler.source>
16+
<maven.compiler.target>17</maven.compiler.target>
17+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
18+
</properties>
19+
20+
<dependencies>
21+
<dependency>
22+
<groupId>io.avaje</groupId>
23+
<artifactId>avaje-inject</artifactId>
24+
<version>${project.version}</version>
25+
<scope>provided</scope>
26+
</dependency>
27+
28+
<!-- annotation processor -->
29+
<dependency>
30+
<groupId>io.avaje</groupId>
31+
<artifactId>avaje-inject-generator</artifactId>
32+
<version>${project.version}</version>
33+
<scope>provided</scope>
34+
</dependency>
35+
36+
</dependencies>
37+
38+
</project>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package org.example.external.aspect;
2+
3+
import io.avaje.inject.aop.Aspect;
4+
import org.example.external.aspect.sub.MyAspectImplementation;
5+
6+
import java.lang.annotation.ElementType;
7+
import java.lang.annotation.Retention;
8+
import java.lang.annotation.RetentionPolicy;
9+
import java.lang.annotation.Target;
10+
11+
@Aspect(target = MyAspectImplementation.class)
12+
@Target(ElementType.METHOD)
13+
@Retention(RetentionPolicy.RUNTIME)
14+
public @interface MyExternalAspect {
15+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
@InjectModule(name = "example-external-aspect")
2+
package org.example.external.aspect;
3+
4+
import io.avaje.inject.InjectModule;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package org.example.external.aspect.sub;
2+
3+
import io.avaje.inject.Component;
4+
import io.avaje.inject.aop.AspectProvider;
5+
import io.avaje.inject.aop.Invocation;
6+
import io.avaje.inject.aop.MethodInterceptor;
7+
import org.example.external.aspect.MyExternalAspect;
8+
9+
import java.lang.reflect.Method;
10+
import java.util.Arrays;
11+
12+
@Component
13+
public class MyAspectImplementation implements AspectProvider<MyExternalAspect>, MethodInterceptor {
14+
15+
@Override
16+
public MethodInterceptor interceptor(Method method, MyExternalAspect aspectAnnotation) {
17+
return this;
18+
}
19+
20+
@Override
21+
public void invoke(Invocation invoke) throws Throwable {
22+
System.out.println("before args: " + Arrays.toString(invoke.arguments()) + " method: " + invoke.method());
23+
try {
24+
invoke.invoke();
25+
} finally {
26+
System.out.println("after method: " + invoke.method());
27+
}
28+
}
29+
}

blackbox-test-inject/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@
1818

1919
<dependencies>
2020

21+
<dependency>
22+
<groupId>io.avaje</groupId>
23+
<artifactId>blackbox-aspect</artifactId>
24+
<version>${project.version}</version>
25+
</dependency>
26+
2127
<dependency>
2228
<groupId>io.avaje</groupId>
2329
<artifactId>avaje-inject</artifactId>

blackbox-test-inject/src/main/java/org/example/myapp/HelloServiceProxy.java

Lines changed: 0 additions & 58 deletions
This file was deleted.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package org.example.myapp;
2+
3+
import io.avaje.inject.Component;
4+
import org.example.external.aspect.MyExternalAspect;
5+
6+
@Component
7+
public class SomeExternalAspectUser {
8+
9+
@MyExternalAspect
10+
public String hello() {
11+
return "hello";
12+
}
13+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package org.example.myapp;
2+
3+
import io.avaje.inject.BeanScope;
4+
import io.avaje.inject.test.TestBeanScope;
5+
import org.junit.jupiter.api.Test;
6+
7+
import static org.assertj.core.api.Assertions.assertThat;
8+
9+
class SomeExternalAspectUserTest {
10+
11+
@Test
12+
void hello() {
13+
try (BeanScope scope = TestBeanScope.builder().build()) {
14+
var some = scope.get(SomeExternalAspectUser.class);
15+
assertThat(some.hello()).isEqualTo("hello");
16+
}
17+
}
18+
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,10 @@ String autoProvides() {
119119
return typeReader.autoProvides();
120120
}
121121

122+
String providesAspect() {
123+
return typeReader.providesAspect();
124+
}
125+
122126
Set<GenericType> allGenericTypes() {
123127
if (allGenericTypes != null) {
124128
return allGenericTypes;

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

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22

33
import io.avaje.inject.spi.Module;
44

5-
import java.util.HashSet;
6-
import java.util.ServiceLoader;
7-
import java.util.Set;
5+
import java.util.*;
86

97
/**
108
* The types provided by other modules in the classpath at compile time.
@@ -16,16 +14,22 @@ final class ExternalProvider {
1614
private final Set<String> providedTypes = new HashSet<>();
1715

1816
void init() {
19-
for (final Module module :
20-
ServiceLoader.load(Module.class, ExternalProvider.class.getClassLoader())) {
21-
for (final Class<?> provide : module.provides()) {
22-
providedTypes.add(provide.getCanonicalName());
23-
}
24-
for (final Class<?> provide : module.autoProvides()) {
25-
providedTypes.add(provide.getCanonicalName());
26-
}
27-
for (final Class<?> provide : module.autoProvidesAspects()) {
28-
providedTypes.add(Constants.ASPECT_PROVIDER + "<" + provide.getCanonicalName() + ">");
17+
ServiceLoader<Module> load = ServiceLoader.load(Module.class, ExternalProvider.class.getClassLoader());
18+
Iterator<Module> iterator = load.iterator();
19+
while (iterator.hasNext()) {
20+
try {
21+
Module module = iterator.next();
22+
for (final Class<?> provide : module.provides()) {
23+
providedTypes.add(provide.getCanonicalName());
24+
}
25+
for (Class<?> provide : module.autoProvides()) {
26+
providedTypes.add(provide.getCanonicalName());
27+
}
28+
for (final Class<?> provide : module.autoProvidesAspects()) {
29+
providedTypes.add(Constants.ASPECT_PROVIDER + "<" + provide.getCanonicalName() + ">");
30+
}
31+
} catch (ServiceConfigurationError expected) {
32+
// ignore expected error reading the module that we are also writing
2933
}
3034
}
3135
}

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

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ final class MetaData {
2121
private final String name;
2222
private String method;
2323
private boolean wired;
24+
private String providesAspect;
2425

2526
/**
2627
* The interfaces and class annotations the bean has (to register into lists).
@@ -38,12 +39,14 @@ final class MetaData {
3839
private String autoProvides;
3940
private boolean generateProxy;
4041
private boolean usesExternalDependency;
42+
private String externalDependency;
4143

4244
MetaData(DependencyMeta meta) {
4345
this.type = meta.type();
4446
this.name = trimName(meta.name());
4547
this.shortType = Util.shortName(type);
4648
this.method = meta.method();
49+
this.providesAspect = meta.providesAspect();
4750
this.provides = asList(meta.provides());
4851
this.dependsOn = Stream.of(meta.dependsOn()).map(Dependency::new).collect(Collectors.toList());
4952
this.autoProvides = meta.autoProvides();
@@ -120,6 +123,7 @@ private List<String> asList(String[] content) {
120123
void update(BeanReader beanReader) {
121124
this.provides = beanReader.provides();
122125
this.dependsOn = beanReader.dependsOn();
126+
this.providesAspect = beanReader.providesAspect();
123127
this.autoProvides = beanReader.autoProvides();
124128
this.generateProxy = beanReader.isGenerateProxy();
125129
}
@@ -140,6 +144,10 @@ String autoProvides() {
140144
return autoProvides;
141145
}
142146

147+
String providesAspect() {
148+
return providesAspect;
149+
}
150+
143151
/**
144152
* Return the top level package for the bean and the interfaces it implements.
145153
*/
@@ -164,7 +172,7 @@ void buildMethod(Append append) {
164172
return;
165173
}
166174
if (usesExternalDependency) {
167-
append.append(" // uses external dependency").append(NEWLINE);
175+
append.append(" // uses external dependency ").append(externalDependency).append(NEWLINE);
168176
}
169177
append.append(" @DependencyMeta(type=\"").append(type).append("\"");
170178
if (name != null) {
@@ -173,7 +181,9 @@ void buildMethod(Append append) {
173181
if (hasMethod()) {
174182
append.append(", method=\"").append(method).append("\"");
175183
}
176-
if (!provides.isEmpty()) {
184+
if (!providesAspect.isEmpty()) {
185+
append.append(", providesAspect=\"").append(providesAspect).append("\"");
186+
} else if (!provides.isEmpty()) {
177187
appendProvides(append, "provides", provides);
178188
}
179189
if (!dependsOn.isEmpty()) {
@@ -227,10 +237,15 @@ void setAutoProvides(String autoProvides) {
227237
this.autoProvides = autoProvides;
228238
}
229239

240+
void setProvidesAspect(String providesAspect) {
241+
this.providesAspect = providesAspect;
242+
}
243+
230244
/**
231245
* This depends on a dependency that comes from another module in the classpath.
232246
*/
233-
void markWithExternalDependency() {
247+
void markWithExternalDependency(String name) {
234248
usesExternalDependency = true;
249+
externalDependency = name;
235250
}
236251
}

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

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,8 @@ final class MetaDataOrdering {
1717
private final Map<String, ProviderList> providers = new HashMap<>();
1818
private final List<DependencyLink> circularDependencies = new ArrayList<>();
1919
private final Set<String> missingDependencyTypes = new LinkedHashSet<>();
20-
private final Set<String> autoRequires = new TreeSet<>();
20+
private final Set<String> autoRequires = new TreeSet<>();
2121
private final Set<String> autoRequiresAspects = new TreeSet<>();
22-
2322

2423
MetaDataOrdering(Collection<MetaData> values, ProcessingContext context, ScopeInfo scopeInfo) {
2524
this.context = context;
@@ -186,18 +185,19 @@ private int processQueueRound(boolean includeExternal) {
186185

187186
private boolean allDependenciesWired(MetaData queuedMeta, boolean includeExternal) {
188187
for (Dependency dependency : queuedMeta.dependsOn()) {
189-
if (!Util.isProvider(dependency.name())) {
188+
final var dependencyName = dependency.name();
189+
if (!Util.isProvider(dependencyName)) {
190190
// check non-provider dependency is satisfied
191-
ProviderList providerList = providers.get(dependency.name());
191+
ProviderList providerList = providers.get(dependencyName);
192192
if (providerList == null) {
193193
if (!scopeInfo.providedByOther(dependency)) {
194-
if (includeExternal && context.externallyProvided(dependency.name())) {
195-
if (Util.isAspectProvider(dependency.name())) {
196-
autoRequiresAspects.add(Util.extractAspectType(dependency.name()));
194+
if (includeExternal && context.externallyProvided(dependencyName)) {
195+
if (Util.isAspectProvider(dependencyName)) {
196+
autoRequiresAspects.add(Util.extractAspectType(dependencyName));
197197
} else {
198-
autoRequires.add(dependency.name());
198+
autoRequires.add(dependencyName);
199199
}
200-
queuedMeta.markWithExternalDependency();
200+
queuedMeta.markWithExternalDependency(dependencyName);
201201
} else {
202202
return false;
203203
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ MetaData createMeta() {
135135
metaData.setDependsOn(dependsOn);
136136
metaData.setProvides(typeReader == null ? Collections.emptyList() : typeReader.provides());
137137
metaData.setAutoProvides(typeReader == null ? null : typeReader.autoProvides());
138+
metaData.setProvidesAspect(typeReader == null ? "" : typeReader.providesAspect());
138139
return metaData;
139140
}
140141

0 commit comments

Comments
 (0)