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代码库中下载示例代码。