Spring @Configuration 注解

Spring `@Configuration` 注解是 Spring 核心框架的一部分。Spring Configuration 注解表示该类具有 `@Bean` 定义方法。因此,Spring 容器可以处理该类并生成 Spring Beans 供应用程序使用。

Spring @Configuration

Spring `@Configuration` 注解允许我们使用注解进行 `依赖注入`。让我们了解如何创建 Spring Configuration 类。让我们创建一个简单的 Java bean 类。

package com.journaldev.spring;

public class MyBean {

	public MyBean() {
		System.out.println("MyBean instance created");
	}
	
}

在我们使用任何 Spring 框架类之前,我们必须将它的依赖项添加到 Maven 项目中。

<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-context</artifactId>
		<version>5.0.6.RELEASE</version>
</dependency>

现在让我们创建 Spring Configuration 类。

package com.journaldev.spring;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyConfiguration {

    @Bean
    public MyBean myBean() {
		return new MyBean();
	}
	
}

让我们编写一个简单的类并配置我们简单的 Spring 配置类。

package com.journaldev.spring;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MySpringApp {

	public static void main(String[] args) {
		AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
		ctx.register(MyConfiguration.class);
		ctx.refresh();

		// MyBean mb1 = ctx.getBean(MyBean.class);

		// MyBean mb2 = ctx.getBean(MyBean.class);

		ctx.close();
	}

}

如果您运行上述应用程序,它将产生如下输出:

May 23, 2018 12:34:54 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@ff5b51f: startup date [Wed May 23 12:34:54 IST 2018]; root of context hierarchy
MyBean instance created
May 23, 2018 12:34:54 PM org.springframework.context.support.AbstractApplicationContext doClose
INFO: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@ff5b51f: startup date [Wed May 23 12:34:54 IST 2018]; root of context hierarchy

注意,Spring 在我们甚至尚未请求之前就将 bean 加载到其上下文中。这是为了确保所有的 bean 都被正确配置,并且如果出现问题,应用程序将快速失败。另外,ctx.refresh() 必须被调用,否则当我们尝试从上下文中获取任何 bean 时,将会出现以下错误。

Exception in thread "main" java.lang.IllegalStateException: org.springframework.context.annotation.AnnotationConfigApplicationContext@f0f2775 has not been refreshed yet
	at org.springframework.context.support.AbstractApplicationContext.assertBeanFactoryActive(AbstractApplicationContext.java:1076)
	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1106)
	at com.journaldev.spring.MySpringApp.main(MySpringApp.java:11)

如果你取消注释我获取 MyBean 实例的语句,你会注意到它并没有调用 MyBean 的构造函数。这是因为spring bean的默认作用域是 Singleton。我们可以使用 @Scope 注解来改变它。

如果我们移除 @Configuration 注解会发生什么?

如果我们从 MyConfiguration 类中移除 @Configuration 注解会发生什么呢?你会注意到它仍然按预期工作,并且 spring bean 被注册并检索为单例类。但在这种情况下,如果我们调用 myBean() 方法,那么它将成为一个普通的 Java 方法调用,我们将获得一个新的 MyBean 实例,并且它将不再是单例的。为了证明这一点,让我们定义另一个 bean,它将使用 MyBean 实例。

package com.journaldev.spring;

public class MyBeanConsumer {

	public MyBeanConsumer(MyBean myBean) {
		System.out.println("MyBeanConsumer created");
		System.out.println("myBean hashcode = "+myBean.hashCode());
	}

}

我们更新后的 Spring 配置类如下:

package com.journaldev.spring;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

//@Configuration
public class MyConfiguration {

	@Bean
    public MyBean myBean() {
		return new MyBean();
	}
	
	@Bean
    public MyBeanConsumer myBeanConsumer() {
		return new MyBeanConsumer(myBean());
	}
}

现在当我们运行MySpringApp类时,它生成以下输出。

MyBean instance created
MyBean instance created
MyBeanConsumer created
myBean hashcode = 1647766367

所以MyBean不再是单例,现在让我们再次用@Configuration注解MyConfiguration并运行MySpringApp类。这次的输出将会是这样。

MyBean instance created
MyBeanConsumer created
myBean hashcode = 1095088856

因此,最好使用@Configuration注解与配置类一起,以确保我们的Spring容器的行为符合我们的期望。如果出于一些奇怪的原因你不想使用@Configuration注解,我们仍然可以通过不调用myBean()方法而是使用通过@Autowired注解配置的MyBean的实例变量来创建我们的配置类。像下面的代码一样也可以工作。

package com.journaldev.spring;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

//@Configuration
public class MyConfiguration {

	@Autowired
	MyBean myBean;
	
	@Bean
    public MyBean myBean() {
		return new MyBean();
	}
	
	@Bean
    public MyBeanConsumer myBeanConsumer() {
		return new MyBeanConsumer(myBean);
	}
}

关于Spring配置注解就介绍到这里,我们将在将来的文章中了解其他Spring注解。

你可以从我们的GitHub存储库下载示例代码。

Source:
https://www.digitalocean.com/community/tutorials/spring-configuration-annotation