求Micronaut中Spring ApplicationContextAware的等效实现(AWS Lambda场景)
在Micronaut中实现Spring的ApplicationContextAware等效功能
背景
在Spring Boot中,我们可以通过ApplicationContextAware接口获取ApplicationContext,从而手动获取容器中的Bean,示例代码如下:
// this is a Spring Boot programme package com.example.demo import org.springframework.context.ApplicationContextAware; public class MyClass implements ApplicationContextAware { private MyBean myBean; private ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) { this.applicationContext= applicationContext; } public void setBean(){ this.myBean= applicationContext.getBean(MyBean.class); } }
我尝试在Micronaut框架中寻找类似方法,试过ApplicationContextConfigurer、ApplicationContextBuilder等类,但都没生效。
补充:将Micronaut应用部署到AWS Lambda后出现NullPointerException,参考Spring相关解决方案推测底层机制类似,附上项目pom.xml:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>MicronautExp</artifactId> <version>0.1</version> <packaging>${packaging}</packaging> <parent> <groupId>io.micronaut</groupId> <artifactId>micronaut-parent</artifactId> <version>3.7.4</version> </parent> <properties> <packaging>jar</packaging> <jdk.version>11</jdk.version> <release.version>11</release.version> <micronaut.version>3.7.4</micronaut.version> <micronaut.runtime>netty</micronaut.runtime> <micronaut.runtime>lambda</micronaut.runtime> <exec.mainClass>com.example.Application</exec.mainClass> <exec.mainClass>io.micronaut.function.aws.runtime.MicronautLambdaRuntime</exec.mainClass> </properties> <repositories> <repository> <id>central</id> <url>https://repo.maven.apache.org/maven2</url> </repository> </repositories> <dependencies> <dependency> <groupId>io.micronaut</groupId> <artifactId>micronaut-inject</artifactId> <scope>compile</scope> </dependency> <dependency> <groupId>io.micronaut</groupId> <artifactId>micronaut-validation</artifactId> <scope>compile</scope> </dependency> <dependency> <groupId>io.micronaut</groupId> <artifactId>micronaut-jackson-databind</artifactId> <scope>compile</scope> </dependency> <dependency> <groupId>jakarta.annotation</groupId> <artifactId>jakarta.annotation-api</artifactId> <scope>compile</scope> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>io.micronaut.test</groupId> <artifactId>micronaut-test-junit5</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.24</version> </dependency> <dependency> <groupId>com.googlecode.json-simple</groupId> <artifactId>json-simple</artifactId> <version>1.1.1</version> </dependency> <!-- micronaut http dependencies. Forgot why they are here, but better not touch it--> <dependency> <groupId>io.micronaut</groupId> <artifactId>micronaut-http-client</artifactId> <scope>compile</scope> </dependency> <dependency> <groupId>io.micronaut</groupId> <artifactId>micronaut-http-server-netty</artifactId> <scope>compile</scope> </dependency> <!-- graalvm compilers. Forgot why they are here, but better not touch it--> <dependency> <groupId>org.graalvm.nativeimage</groupId> <artifactId>svm</artifactId> <version>22.2.0</version> </dependency> <dependency> <groupId>org.graalvm.sdk</groupId> <artifactId>graal-sdk</artifactId> <version>22.2.0</version> </dependency> <!-- micronaut email dependency--> <dependency> <groupId>io.micronaut.email</groupId> <artifactId>micronaut-email-javamail</artifactId> </dependency> <dependency> <groupId>io.micronaut.email</groupId> <artifactId>micronaut-email</artifactId> <version>1.5.0</version> </dependency> <!-- AWS Lambda dependencies--> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>io.micronaut.aws</groupId> <artifactId>micronaut-function-aws-api-proxy</artifactId> <scope>compile</scope> </dependency> <dependency> <groupId>io.micronaut.aws</groupId> <artifactId>micronaut-function-aws-api-proxy-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>io.micronaut.aws</groupId> <artifactId>micronaut-function-aws-custom-runtime</artifactId> <scope>compile</scope> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.12.0</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>io.micronaut.build</groupId> <artifactId>micronaut-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.10.1</version> <configuration> <!-- Uncomment to enable incremental compilation --> <!-- <useIncrementalCompilation>false</useIncrementalCompilation> --> <annotationProcessorPaths combine.children="append"> <path> <groupId>io.micronaut</groupId> <artifactId>micronaut-http-validation</artifactId> <version>${micronaut.version}</version> </path> </annotationProcessorPaths> <compilerArgs> <arg>-Amicronaut.processing.group=com.example</arg> <arg>-Amicronaut.processing.module=MicronautExp</arg> </compilerArgs> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>2.4.3</version> <configuration> <createDependencyReducedPom>false</createDependencyReducedPom> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
解决方案
在Micronaut中,对应Spring的ApplicationContextAware的等效实现有两种常用方式,针对AWS Lambda场景优化如下:
方式1:注入BeanContext
Micronaut的BeanContext是Spring ApplicationContext的直接替代,你可以直接通过构造函数或字段注入的方式获取它,然后手动获取Bean:
package com.example; import io.micronaut.context.BeanContext; import jakarta.inject.Singleton; @Singleton public class MyClass { private final MyBean myBean; // 构造函数注入BeanContext并直接获取MyBean public MyClass(BeanContext beanContext) { this.myBean = beanContext.getBean(MyBean.class); } // 或者如果需要延迟获取,保留BeanContext引用 // private final BeanContext beanContext; // public MyClass(BeanContext beanContext) { // this.beanContext = beanContext; // } // public void setBean() { // this.myBean = beanContext.getBean(MyBean.class); // } }
方式2:实现BeanContextAware接口
Micronaut提供了BeanContextAware接口,用法和Spring的ApplicationContextAware几乎一致:
package com.example; import io.micronaut.context.BeanContext; import io.micronaut.context.BeanContextAware; import jakarta.inject.Singleton; @Singleton public class MyClass implements BeanContextAware { private MyBean myBean; private BeanContext beanContext; @Override public void setBeanContext(BeanContext beanContext) { this.beanContext = beanContext; } public void setBean() { this.myBean = beanContext.getBean(MyBean.class); } }
AWS Lambda场景注意事项
- 确保类被Micronaut管理:你的
MyClass和MyBean必须添加@Singleton(或其他作用域注解),确保被Micronaut的容器扫描并管理。 - Lambda入口类的正确配置:如果你的Lambda handler类不是被容器管理的,需要在入口处手动获取
BeanContext。例如:
package com.example; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import io.micronaut.context.ApplicationContext; public class LambdaHandler implements RequestHandler<Object, Object> { private static final ApplicationContext CONTEXT = ApplicationContext.run(); private final MyClass myClass = CONTEXT.getBean(MyClass.class); @Override public Object handleRequest(Object input, Context context) { // 使用myClass处理请求 myClass.setBean(); return "Success"; } }
- 移除pom.xml中重复配置:你的pom.xml里
micronaut.runtime和exec.mainClass有重复定义,建议保留lambdaruntime和MicronautLambdaRuntime主类,避免初始化冲突。
内容的提问来源于stack exchange,提问作者cliff_leaf
相关产品推荐
相关产品推荐

