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

相關文章
相關標籤/搜索