zno2

@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,设置构造参数也是同理

 

posted on 2023-07-13 18:01  zno2  阅读(18)  评论(0编辑  收藏  举报

导航