Spring 5 支持在应用程序上下文中以函数式方式注册 bean。
简单地说,您可以通过在 GenericApplicationContext 类中定义的一个新的 registerBean() 方法重载来完成。
让我们来为此功能列举一些例子。
建立 Spring 5 项目的最快方式是将 spring-boot-start-parent 依赖添加到 pom.xml 中来使用 Spring Boot:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.0.M1</version> <relativePath/> </parent>
我们的示例需要到 spring-boot-starter-web 和 spring-boot-starter-test ,且在 JUnit 测试中需要使用到 WebApplicationContext:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
当然,使用函数式的方式来注册一个 bean,Spring Boot 并不是必需的。 我们也可以直接添加 spring-core 依赖 [1]:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>5.0.0.RC2</version> </dependency>
由于 Maven Central 仓库中尚未存在这些版本 [1],我们需要将 Spring Snapshot Repository 添加到 pom.xml 文件中:
<repositories> <repository> <id>spring-snapshot</id> <name>Spring Snapshot Repository</name> <url>https://repo.spring.io/snapshot</url> <snapshots> <enabled>true</enabled> </snapshots> </repository> </repositories>
首先,我们创建一个非常简单的类,使用它来创建 bean:
public class MyService{ public int getRandomNumber(){ return new Random().nextInt(10); } }
我们再添加一个 @SpringBootApplication 类,可以使用它来运行 JUnit 测试:
@SpringBootApplication public class Spring5Application{ public static void main(String[] args){ SpringApplication.run(Spring5Application.class, args); } }
接下来,我们可以使用 @SpringBootTest 注解设置我们的测试类来创建一个 GenericWebApplicationContext 实例:
@RunWith(SpringRunner.class) @SpringBootTest(classes = Spring5Application.class) public class BeanRegistrationTest{ @Autowired private GenericWebApplicationContext context; //... }
我们在示例中使用了 GenericWebApplicationContext 类型,但任何类型的 ApplicationContext 都可以以相同的方式来注册一个 bean。
让我们看看如何 使用 lambda 表达式注册一个 bean 以创建实例 :
context.registerBean(MyService.class, () -> new MyService());
我们来验证一下可不可以检索到该 bean 并使用它:
MyService myService = (MyService) context.getBean("com.baeldung.functional.MyService"); assertTrue(myService.getRandomNumber() < 10);
在该例子中我们可以看到,如果没有明确定义 bean 的名称,那么它将根据小写的类名来确定。上述方法也可以与一个显式的 bean 名称一起使用:
context.registerBean("mySecondService", MyService.class, () -> new MyService());
接下来,让我们来看看 如何通过添加一个 lambda 表达式来自定义注册一个 bean :
context.registerBean("myCallbackService", MyService.class, () -> new MyService(), bd -> bd.setAutowireCandidate(false));
这个参数是一个函数式回调,我们可以使用它来设置 bean 属性,如 autowire-candidate 标志或 primary 标志。
在本教程中,我们了解了如何以函数式方式来注册一个 bean。
该示例的源代码可以在 GitHub 上找到。