|
3 | 3 |
|
4 | 4 | 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.
|
5 | 5 |
|
| 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 | + |
6 | 63 | === Contributing new hints
|
7 | 64 |
|
8 | 65 | The typical approach is:
|
|
0 commit comments