Skip to content
This repository was archived by the owner on Feb 23, 2023. It is now read-only.

Commit d6d646f

Browse files
committed
Introduce native applications guidelines for Spring contributors
Closes gh-256
1 parent d065294 commit d6d646f

File tree

2 files changed

+61
-6
lines changed

2 files changed

+61
-6
lines changed

spring-native-docs/src/main/asciidoc/how-to-contribute.adoc

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,63 @@
33

44
This section describes how to extend Spring Native. You can then https://github.com/spring-projects-experimental/spring-native/pulls[submit pull requests] in order to add support for a specific part of Spring ecosystem.
55

6+
=== Designing native-friendly Spring libraries
7+
8+
Native support is mostly about making an application and its libraries possible to analyze at build-time to configure
9+
what's required or not at runtime. The goal is to do that in an optimal way to have a minimal footprint.
10+
11+
Spring applications are dynamic, hence the use for example of reflection in various places. Spring Native and its
12+
Spring AOT build plugins performs AOT transformations, in the context of a specific application classpath and configuration
13+
in order to generate the optimal native configuration, but also programmatic versions of `spring.factories` or auto-configurations
14+
that reduce the amount of reflection required. Each reflection entry (per constructor/method/field) leads to the creation
15+
of a proxy class by `native-image`, so from a footprint point of view, those AOT transformation allow to increase
16+
Spring native application efficiency.
17+
18+
The documentation above provides native best practices useful for Spring libraries contributor.
19+
20+
=== Use `proxyBeanMethods=false` in `@Configuration` classes provided by a library
21+
22+
In native applications, `@Bean` annotated methods do not support cross `@Bean` invocations since they require a CGLIB
23+
proxy created at runtime. This is similar to the behavior you get with the so called
24+
https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-java-basic-concepts[lite mode] or
25+
with https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Configuration.html#proxyBeanMethods--[`@Configuration(proxyBeanMethods=false)`].
26+
27+
It is fine for applications to just use `@Configuration` without setting `proxyBeanMethods=false`
28+
and use method parameters to inject bean dependencies, this is handled by Spring Native to not require
29+
a CGLIB proxy.
30+
31+
Libraries are encouraged to use `@Configuration(proxyBeanMethods=false)`
32+
(most of Spring portfolio currently uses this variant) since it is generally a good idea to avoid CGLIB proxies if
33+
not needed and to provide native compatibility.
34+
This behavior could potentially become the default in a future Spring Framework version.
35+
36+
==== Use NativeDetector for native conditional code paths
37+
38+
Spring related code should use `NativeDetector.inNativeImage()` (provided by `spring-core` dependency) to detect
39+
native-specific code paths. Spring Framework or Spring Data takes advantage of this utility method to disable CGLIB
40+
proxies since they are not support on native images for example.
41+
42+
==== Do classpath checks in static block/fields and configure build-time initialization
43+
44+
In order to reduce the footprint of the native image, a useful optimization consist in:
45+
46+
* Make sure that the classpath check is done in static block/fields
47+
* Configure the class to be initialized at build-time using `@NativeHint`
48+
49+
As a result, the classpath check will be done during the native image build, and the optional classes will be bundled
50+
in the native image only if required. Limit the number of classes initialized at build-time since that could quickly
51+
become viral and can trigger compatibility issues, hence the runtime default.
52+
53+
==== Try to favor functional approaches or move reflection at build-time
54+
55+
For code ran at runtime, try to favor functional approaches like lambdas and method references instead of reflection
56+
when possible, since they are automatically understood by the native image compiler.
57+
58+
It is perflectly fine to use reflection in native world but at build-time:
59+
60+
* In the static block/fields of a class initialized at build-time
61+
* In an AOT transformation ran by Spring AOT build plugin
62+
663
=== Contributing new hints
764

865
The typical approach is:

spring-native-docs/src/main/asciidoc/support.adoc

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,8 @@ Group ID is `org.springframework.cloud`.
102102

103103
=== Limitations
104104

105-
In native applications, `@Bean` annotated methods do not support cross `@Bean` invocations since they require a CGLIB proxy created at runtime.
106-
This is similar to the behavior you get with the so called https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-java-basic-concepts[lite mode] or with https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Configuration.html#proxyBeanMethods--[`@Configuration(proxyBeanMethods=false)`].
107-
It is fine for applications to just use `@Configuration` without setting `proxyBeanMethods=false` and use method parameters to inject bean dependencies.
108-
Libraries are encouraged to use `@Configuration(proxyBeanMethods=false)` (most of Spring portfolio currently uses this variant) since it is generally a good idea to avoid CGLIB proxies if not needed and to provide native compatibility.
109-
This behavior could potentially become the default in a future Spring Framework version.
105+
CGLIB proxies are not supported, only JDK dynamic proxies on interfaces are supported for now.
110106

111-
Only proxies on interfaces are supported for now.
107+
It is fine for applications to just use `@Configuration` without setting `proxyBeanMethods=false`
108+
and use method parameters to inject bean dependencies, this is handled by Spring Native to not require
109+
a CGLIB proxy.

0 commit comments

Comments
 (0)