Spring - Java-based configuration: Using @Configuration

@Configuration

这是一个类级注解。以下所示,被它注解的类可能包含多个被@Bean注解的方法。Spring容器会调用这些方法,得到你初始化后的对象实例,并把他们注册为容器内的beans。html

package spring.example

@Configuration
public class MyAppConfig {
    @bean
    public SomeBean someBean() {
        // 实例化并返回,也可进行初始化
        return new SomeBeanImpl();
    }
}

同等做用的XML配置会像下面这样:java

<bean name="someBean" class="spring.example.SomeBeanImpl"/>

clipboard.png

@Configuration类们实际上就是Spring管理的用于建立并注册bean实例的工厂。spring

Spring容器的启动

在Java-based的配置方式下,spring容器能够被AnnotationConfigApplicationContext启动,或者,针对Web应用AnnotationConfigWebApplicationContext也行。缓存

new AnnotationConfigApplicationContext(MyAppConfig.class);

咱们也能够指定包含了@Configuration类的有效包名:app

new AnnotationConfigApplicationContext("spring.example");

基于上述两个重载方法,咱们能够在单个package下放进多个JavaConfig类。this

使用多个JavaConfig类

new AnnotationConfigApplicationContext( AppConfig.class, DataSourceConfig.class );
new AnnotationConfigApplicationContext("example.spring.app","example.spring.datasource");

配置类中的依赖注入

既然配置类会被Spring容器注册成beans,那意味着,咱们能够像使用普通bean那样使用这个配置bean。在如下例子咱们要把这个一个配置bean注入给另外一个配置bean:spa

@Configuration
public class AppConfig {
    // 方式一:注入DataSourceConfig
    @Autowired
    private DataSourceConfig dataSourceConfig;

    @Bean
    Client clientBean() {
        return new Client(dataSourceConfig.dataSourceBean());
    }

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context =
          new AnnotationConfigApplicationContext(AppConfig.class, DataSourceConfig.class);
        context.getBean(Client.class).showData();
    }
    
    
    // 方式二:为什么要那么麻烦呢?直接注入DataSourceBean不就行了?
    @Autowired
    private DataSourceBean dataSourceBean;

    @Bean
    Client clientBean() {
        return new Client(dataSourceBean);
    }
}

@Configuration
class DataSourceConfig {

    @Bean
    DataSourceBean dataSourceBean() {
        return new DataSourceBean();
    }
}

class Client {
    private DataSourceBean dataSourceBean;

    Client(DataSourceBean dataSourceBean){
        this.dataSourceBean = dataSourceBean;
    }

    public void showData() {
        System.out.println(dataSourceBean.getData());
    }
}

class DataSourceBean {

    public String getData() {
        return "some data";
    }
}

在JavaConfig中使用构造器注入

从Spring 4.3开始,配置类开始支持使用构造器注入,能够从如下例子感觉下何种场景下可使用这个特性,see also:Spring - Implicit constructor Injection代理

@Configuration
@ComponentScan({"com.logicbig.example.service", "com.logicbig.example.client"})
public class ConfigurationImplicitConstructor {

    private final OrderService orderService;

    public ConfigurationImplicitConstructor (OrderService orderService) {
        this.orderService = orderService;
    }

    @Bean(name = "services")
    public List<OrderService> services(){
        return Arrays.asList(orderService);
    }


    public static void main (String... strings) {
       AnnotationConfigApplicationContext context =
                           new AnnotationConfigApplicationContext(
                                               ConfigurationImplicitConstructor.class);
       Object services = context.getBean("services");
        System.out.println(services);
   }


}

@Configuration类都会被CGLIB子类化

全部的@Configuration类都会在应用启动阶段被CGLIB进行子类化。在生成的子类当中,子方法会首先检查容器内已缓存的beans,若是已缓存的beans中没有当前实例,子方法才会真正去调用父方法,便是真正建立一个新的对象实例
在@Configuration类的@Bean方法中调用的[方法或字段],就是经过CGLIB代理,去对协做对象建立bean元数据引用。

这同时也是为什么屡次调用同一方法时,只会返回同一个实例的缘由(由于默认的scoped为singleton)。
@Configuration注解是必须的,不然这个CGLIB代理不会被Spring执行。
运行如下代码,你能够看到输出结果是一致的。另外也能够把@Configuration去掉后,再运行看看结果。code

@Configuration
public class SpringConfig {

    @Bean
    public String something(){
        return new String(System.nanoTime());
    }

    public static void main(String... strings) {
        AnnotationConfigApplicationContext context =
              new AnnotationConfigApplicationContext(SpringConfig.class);
        System.out.println("Spring container started and is ready");
        SpringConfig bean = context.getBean(SpringConfig.class);
        System.out.println(bean.something());
        System.out.println(bean.something());
    }
}

请注意在上例中,SpringConfig是做为一个bean实例被咱们获取到的。这也是@Configuration类会被做为bean注册的一个有力证实。xml

相关文章
相关标签/搜索