Spring @Configuration注解详解:原理、使用方法与实例

这是文章《Spring的@Configuration注解》的第1部分(共1部分)。

内容片段: @Spring注解是Spring核心框架的一部分。@Spring配置注解表示该类具有@Bean定义方法。因此,Spring容器可以处理该类并生成用于应用程序的Spring Beans。

Spring的@Configuration注解

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

package com.Olivia.spring;

public class MyBean {

	public MyBean() {
		System.out.println("MyBean实例已创建");
	}
	
}

在使用任何Spring框架类之前,我们需要将其依赖项添加到Maven项目中。

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

现在让我们创建Spring配置类。

package com.Olivia.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.Olivia.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实例已创建
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.Olivia.spring.MySpringApp.main(MySpringApp.java:11)

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

如果我们移除@Configuration注解,会怎样呢?

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

package com.Olivia.spring;

public class MyBeanConsumer {

	public MyBeanConsumer(MyBean myBean) {
		System.out.println("MyBeanConsumer已创建");
		System.out.println("myBean哈希码 = "+myBean.hashCode());
	}

}

我们更新后的Spring配置类是:

package com.Olivia.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实例已创建
MyBean实例已创建
MyBeanConsumer已创建
myBean哈希码 = 1647766367

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

MyBean实例已创建
MyBeanConsumer已创建
myBean哈希码 = 1095088856

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

package com.Olivia.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 Configuration注解的内容就介绍到这里,我们将在未来的文章中深入了解其他的Spring注解。

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

bannerAds