@Configration
Open Declaration org.springframework.context.annotation.Configuration
@Target(value={TYPE})
@Retention(value=RUNTIME)
@Documented
@Component
Indicates that a class declares one or more @Bean methods and may be processedby the Spring container to generate bean definitions and service requests for thosebeans at runtime, for example:
@Configuration
public class AppConfig {
@Bean
public MyBean myBean() {
// instantiate, configure and return bean ...
}
}
Bootstrapping @Configuration classes
Via AnnotationConfigApplicationContext
@Configuration classes are typically bootstrapped using either AnnotationConfigApplicationContext or its web-capable variant, AnnotationConfigWebApplicationContext.A simple example with the former follows:
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(AppConfig.class);
ctx.refresh();
MyBean myBean = ctx.getBean(MyBean.class);
// use myBean ...
See AnnotationConfigApplicationContext Javadoc for further details and see AnnotationConfigWebApplicationContext for web.xml configuration instructions.
Via Spring <beans> XML
As an alternative to registering @Configuration classes directly against an AnnotationConfigApplicationContext, @Configuration classes may bedeclared as normal <bean> definitions within Spring XML files:
<beans>
<context:annotation-config/>
<bean class="com.acme.AppConfig"/>
</beans>
In the example above, <context:annotation-config/> is required in order toenable ConfigurationClassPostProcessor and other annotation-relatedpost processors that facilitate handling @Configuration classes.
Via component scanning
@Configuration is meta-annotated with @Component, therefore @Configuration classes are candidates for component scanning (typically usingSpring XML's <context:component-scan/> element) and therefore may also takeadvantage of @Autowired/@Injectat the field and method level (but not at the constructor level).
@Configuration classes may not only be bootstrapped usingcomponent scanning, but may also themselves configure component scanning usingthe @ComponentScan annotation:
@Configuration
@ComponentScan("com.acme.app.services")
public class AppConfig {
// various @Bean definitions ...
}
See @ComponentScan Javadoc for details.
Working with externalized values
Using the Environment API
Externalized values may be looked up by injecting the Spring Environment into a @Configuration class using the @Autowired or the @Injectannotation: @Configuration
public class AppConfig {
@Inject
Environment env;
@Bean
public MyBean myBean() {
MyBean myBean = new MyBean();
myBean.setName(env.getProperty("bean.name"));
return myBean;
}
}
Properties resolved through the Environment reside in one or more "propertysource" objects, and @Configuration classes may contribute property sources tothe Environment object usingthe @PropertySources annotation: @Configuration
@PropertySource("classpath:/com/acme/app.properties")
public class AppConfig {
@Inject Environment env;
@Bean
public MyBean myBean() {
return new MyBean(env.getProperty("bean.name"));
}
}
See Environmentand @PropertySource Javadoc for further details.
Using the @Value annotation
Externalized values may be 'wired into' @Configuration classes usingthe @Value annotation: @Configuration
@PropertySource("classpath:/com/acme/app.properties")
public class AppConfig {
@Value("${bean.name}") String beanName;
@Bean
public MyBean myBean() {
return new MyBean(beanName);
}
}
This approach is most useful when using Spring's PropertySourcesPlaceholderConfigurer, usually enabled via XML with <context:property-placeholder/>. See the section below on composing @Configuration classes with Spring XML using @ImportResource,see @Value Javadoc, and see @Bean Javadoc for details on working with BeanFactoryPostProcessor types such as PropertySourcesPlaceholderConfigurer.
Composing @Configuration classes
With the @Import annotation
@Configuration classes may be composed using the @Import annotation,not unlike the way that <import> works in Spring XML. Because @Configuration objects are managed as Spring beans within the container,imported configurations may be injected using @Autowired or @Inject:
@Configuration
public class DatabaseConfig {
@Bean
public DataSource dataSource() {
// instantiate, configure and return DataSource
}
}
@Configuration
@Import(DatabaseConfig.class)
public class AppConfig {
@Inject DatabaseConfig dataConfig;
@Bean
public MyBean myBean() {
// reference the dataSource() bean method
return new MyBean(dataConfig.dataSource());
}
}
Now both AppConfig and the imported DatabaseConfig can be bootstrappedby registering only AppConfig against the Spring context: new AnnotationConfigApplicationContext(AppConfig.class);
With the @Profile annotation
@Configuration classes may be marked with the @Profile annotation toindicate they should be processed only if a given profile or profiles are active: @Profile("embedded")
@Configuration
public class EmbeddedDatabaseConfig {
@Bean
public DataSource dataSource() {
// instantiate, configure and return embedded DataSource
}
}
@Profile("production")
@Configuration
public class ProductionDatabaseConfig {
@Bean
public DataSource dataSource() {
// instantiate, configure and return production DataSource
}
}
See @Profile and EnvironmentJavadoc for further details.
With Spring XML using the @ImportResource annotation
As mentioned above, @Configuration classes may be declared as regular Spring <bean> definitions within Spring XML files. It is also possible toimport Spring XML configuration files into @Configuration classes usingthe @ImportResource annotation. Bean definitions imported from XML can beinjected using @Autowired or @Inject: @Configuration
@ImportResource("classpath:/com/acme/database-config.xml")
public class AppConfig {
@Inject DataSource dataSource; // from XML
@Bean
public MyBean myBean() {
// inject the XML-defined dataSource bean
return new MyBean(this.dataSource);
}
}
With nested @Configuration classes
@Configuration classes may be nested within one another as follows: @Configuration
public class AppConfig {
@Inject DataSource dataSource;
@Bean
public MyBean myBean() {
return new MyBean(dataSource);
}
@Configuration
static class DatabaseConfig {
@Bean
DataSource dataSource() {
return new EmbeddedDatabaseBuilder().build();
}
}
}
When bootstrapping such an arrangement, only AppConfig need be registeredagainst the application context. By virtue of being a nested @Configurationclass, DatabaseConfig will be registered automatically. This avoidsthe need to use an @Import annotation when the relationship between AppConfig DatabaseConfig is already implicitly clear.
Note also that nested @Configuration classes can be used to good effectwith the @Profile annotation to provide two options of the same bean to theenclosing @Configuration class.
Configuring lazy initialization
By default, @Bean methods will be eagerly instantiated at containerbootstrap time. To avoid this, @Configuration may be used in conjunction withthe @Lazy annotation to indicate that all @Bean methods declared withinthe class are by default lazily initialized. Note that @Lazy may be used onindividual @Bean methods as well.
Testing support for @Configuration classes
The Spring TestContext framework available in the spring-test moduleprovides the @ContextConfiguration annotation, which as of Spring 3.1 canaccept an array of @Configuration Class objects: @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={AppConfig.class, DatabaseConfig.class})
public class MyTests {
@Autowired
MyBean myBean;
@Autowired
DataSource dataSource;
@Test
public void test() {
// assertions against myBean ...
}
}
See TestContext framework reference documentation for details.
Enabling built-in Spring features using @Enable annotations
Spring features such as asynchronous method execution, scheduled task execution,annotation driven transaction management, and even Spring MVC can be enabled andconfigured from @Configurationclasses using their respective "@Enable" annotations. See @EnableAsync, @EnableScheduling, @EnableTransactionManagement, @EnableAspectJAutoProxy,and @EnableWebMvcfor details.
Constraints when authoring @Configuration classes
•@Configuration classes must be non-final
•@Configuration classes must be non-local (may not be declared within a method)
•@Configuration classes must have a default/no-arg constructor and may not use @Autowired constructor parameters. Any nested configuration classesmust be static.
Since:3.0Author:Rod JohnsonChris BeamsSee Also:BeanProfileImportImportResourceComponentScanLazyPropertySourceAnnotationConfigApplicationContextConfigurationClassPostProcessororg.springframework.core.env.Environmentorg.springframework.test.context.ContextConfiguration
一、是哪个功能的替代品
spring bean configuration file 即 aaa.xml
功能:
import other xml
component scan
properties
profile
二、入口
1. junit
@Configuration public class Aconf { }
import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @ContextConfiguration(classes = { Aconf.class }) @RunWith(SpringJUnit4ClassRunner.class) public class ConfTest { @Autowired private ApplicationContext ap; @Test public void ff() { System.out.println(ap.getStartupDate()); } }
2. main
import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Configuration; @Configuration public class Aconf { public static void main(String[] args) { ApplicationContext ap = new AnnotationConfigApplicationContext(Aconf.class); System.out.println(ap.getStartupDate()); } }
3. spring boot
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
三、实现方式
1. 声明一个配置
@Configuration public class Aconf { }
2. 注册一个 bean
public class Foo { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
@Configuration public class Aconf { @Bean public Object getFoo() { Foo foo = new Foo(); foo.setName("aaa"); return foo; } }
import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @ContextConfiguration(classes = { Aconf.class }) @RunWith(SpringJUnit4ClassRunner.class) public class ConfTest { @Autowired private Foo foo; @Test public void ff() { System.out.println(foo.getName()); } }
3. 引入properties
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; @Configuration @PropertySource("classpath:conf/a.properties") public class Aconf { }
src/main/resources/conf/a.properties
foo.name = bbbb
@ContextConfiguration(classes = { Aconf.class })
@RunWith(SpringJUnit4ClassRunner.class)
public class ConfTest {
@Autowired
private Environment env;
@Test
public void ff() {
System.out.println(env.getProperty("foo.name"));
}
}
4. 引入其他配置
import org.springframework.context.annotation.Configuration; @Configuration public class Bconf { }
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @Configuration @Import(Bconf.class) public class Aconf { }
import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @ContextConfiguration(classes = { Aconf.class }) @RunWith(SpringJUnit4ClassRunner.class) public class ConfTest { @Autowired private ApplicationContext app; @Test public void ff() { System.out.println(app.getStartupDate()); } }
5. 引入 xml 配置
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ImportResource; @Configuration @ImportResource("classpath:spring/root/cconf.xml") public class Aconf { }
src/main/resources/spring/root/cconf.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> </beans>
import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @ContextConfiguration(classes = { Aconf.class }) @RunWith(SpringJUnit4ClassRunner.class) public class ConfTest { @Autowired private ApplicationContext app; @Test public void ff() { System.out.println(app.getStartupDate()); } }
6. 组件扫描
package cn.zno.testconf; import org.springframework.stereotype.Component; @Component public class Foo { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan("cn.zno.testconf") public class Aconf { }
import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @ContextConfiguration(classes = { Aconf.class }) @RunWith(SpringJUnit4ClassRunner.class) public class ConfTest { @Autowired private Foo foo; @Test public void ff() { assert(foo != null); } }
7. profile
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; @Configuration @Profile("production") public class Aconf { }
如何激活profile 呢?
补充:2022-08-03
@Configuration 的是对 xml 配置的java实现,其中属性注入顺序是:
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Component; @ConfigurationProperties(prefix="foo") @Configuration public class FooConfig implements InitializingBean{ static { System.setProperty("foo.name", "apple"); } private String name; @Autowired(required=false) private Foo foo; @Autowired(required=false) private Woo woo; @Autowired(required=false) private Hoo hoo; public FooConfig() { System.out.println("构造FooConfig"); } @Bean public Foo initFoo(Woo woo) { System.out.println("---------initFoo---------"); System.out.println("this.name=" + this.name); System.out.println("this.foo=" + this.foo); System.out.println("this.woo=" + this.woo); System.out.println("this.hoo=" + this.hoo); System.out.println("woo=" + woo); return new Foo(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public static class Foo { public Foo() { System.out.println("构造Foo"); } } @Component public static class Woo { public Woo() { System.out.println("构造Woo"); } } @Component public static class Hoo { public Hoo() { System.out.println("构造Hoo"); } } @Override public void afterPropertiesSet() throws Exception { System.out.println("---------afterPropertiesSet---------"); System.out.println("this.name=" + this.name); System.out.println("this.foo=" + this.foo); System.out.println("this.woo=" + this.woo); System.out.println("this.hoo=" + this.hoo); System.out.println("hoo=" + hoo); } }
启动后输出:
构造Hoo 构造Woo 构造FooConfig ---------initFoo--------- this.name=null this.foo=null this.woo=null this.hoo=null woo=cn.xs.qishi.online.jim.config.FooConfig$Woo@333e5fb6 构造Foo ---------afterPropertiesSet--------- this.name=apple this.foo=cn.xs.qishi.online.jim.config.FooConfig$Foo@2804b13f this.woo=cn.xs.qishi.online.jim.config.FooConfig$Woo@333e5fb6 this.hoo=cn.xs.qishi.online.jim.config.FooConfig$Hoo@69069866 hoo=cn.xs.qishi.online.jim.config.FooConfig$Hoo@69069866
小结:
1)先扫描并初始化@Component ,然后初始化 @Configuration ,然后尝试初始化@Bean ,如果某个Bean有入参则视作构造函数提前构造,最后才是@Autowired 和 @ConfigurationProperties
2)initFoo 可以看出FooConfig 、Hoo、Woo 已经实例化,但是fooConfig 中并没提前注入foo等
3)@Configuration 是对xml的java实现,配置<bean /> 的方式变成了@Bean,设置构造参数也是同理
浙公网安备 33010602011771号