多個配置元數據的合併

多個配置元數據的合併

在實際開發中,一般不會將所有的配置元數據放到同一個XML(或基於Java的配置類)中。

因爲配置元數據也有主次(或稱爲父子)之分,這樣結構分明,也便於管理便於協同開發

舉個例子,可以將MVC架構中,將Dao層和Service層的JavaBean配置在不同的配置元數據中,再使用一個總的配置元數據,將Dao層和Service層的配置元數據合併起來(類似於C語言的include頭文件引入)。

Service層的配置元數據:

@Configuration
public class ServiceConfig {

    @Bean
    public TransferService transferService(AccountRepository accountRepository) {
        return new TransferServiceImpl(accountRepository);
    }
}

Dao層的配置元數據:

@Configuration
public class RepositoryConfig {

    @Bean
    public AccountRepository accountRepository(DataSource dataSource) {
        return new JdbcAccountRepository(dataSource);
    }
}

總的配置元數據

@Configuration
@Import({ServiceConfig.class, RepositoryConfig.class})
public class SystemTestConfig {

    @Bean
    public DataSource dataSource() {
        // return new DataSource
    }
}

上面展示了基於Java的配置元數據的合併,接下來仔細討論不同的合併方式。

1.基於XML

<import/>標籤

<beans>
    <import resource="services.xml"/>
    <import resource="resources/messageSource.xml"/>
    <import resource="/resources/themeSource.xml"/>

    <bean id="bean1" class="..."/>
    <bean id="bean2" class="..."/>
</beans>

多個XML傳入構造器

當容器創建時,可以將多個XML文件通過參數傳遞給構造器,進而實現配置元數據的和並。

ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");

2.基於註解

基於註解的配置,需要在XML中寫入掃描包的路徑;甚至,是XML和註解混合使用的。

這個時候,可以使用上面基於XML的方式進行合併,也可以增加掃描包的路徑,來實現配置元數據的合併。

3.基於Java的合併

通過@import註解

public class ServiceConfig {

    @Bean
    public TransferService transferService(AccountRepository accountRepository) {
        return new TransferServiceImpl(accountRepository);
    }
}

public class RepositoryConfig {

    @Bean
    public AccountRepository accountRepository(DataSource dataSource) {
        return new JdbcAccountRepository(dataSource);
    }
}

@Configuration
@Import({ServiceConfig.class, RepositoryConfig.class})
public class SystemTestConfig {

    @Bean
    public DataSource dataSource() {
        // return new DataSource
    }
}

乍一看和第一開始舉的例子一樣,仔細觀察,這裏我把ServiceConfig和RepositoryConfig兩個配置類的@Configuration註解去掉了

@Configuration註解的作用是在包掃描的時候,讓容器“知道”這個類是一個配置類。如果在構建容器時,給容器傳入的參數是SystemTestConfig(上面的例子),SystemTestConfig的@Configuration也可以不用。

@ComponentScan包掃描註解

@Configuration
public class ServiceConfig {

    @Bean
    public TransferService transferService(AccountRepository accountRepository) {
        return new TransferServiceImpl(accountRepository);
    }
}

@Configuration
public class RepositoryConfig {

    @Bean
    public AccountRepository accountRepository(DataSource dataSource) {
        return new JdbcAccountRepository(dataSource);
    }
}

@Configuration
@ComponentScan(basePackages="org.cinfiguration")
public class SystemTestConfig {

    @Bean
    public DataSource dataSource() {
        // return new DataSource
    }
}

在上面提到過,@Configuration是爲了包掃描的時候,可以讓容器“知道”這個類是一個配置類。所以,在加載SystemTestConfig這個配置類時,因爲它被@ComponentScan標註,所以會掃描它指定的包,將這些包下的帶有@Configuration的類,當作配置元數據加載。

@ComponentScan不僅能加載配置元數據,對於基於註解的配置元數據(@AutoWired等),也可以使用@CompentScan掃描並加載

多個配置類傳入構造器

與傳入多個XML文件類似,也可以傳入多個配置類。

 ApplicationContext ctx = new AnnotationConfigApplicationContext(MyServiceImpl.class, Dependency1.class, Dependency2.class);

4.基於Java的配置和基於XML的配置的合併

一開始像這個問題可能會比較懵,構建容器時,要麼傳入XML文件,要麼傳入Class<?>對象,這兩個怎麼混合?

@ImportResource + AnnotationConfigApplicationContext

使用@ImportResource標註配置類,可以指定XML文件,實現Java配置類和XML配置元數據的合併。


//基於Java的配置類
@ImportResource("classpath:/com/commons/Config/beans.xml")
public class AppConfig {
	//Java配置...
}


ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

context:component-scan + ClassPathXmlApplicationContext

上面提到過,@Configuration註解的作用是在包掃描的時候,讓容器“知道”這個類是一個配置類。也就是說一旦包掃描過程中,彭帶Configuration,就會把這個類當作配置元數據加載

知道了這一點,就簡單了,在XML中寫入包掃描的路徑,當構建容器時,掃描到被@Configuration標註的類,就會被擋做配置元數據加載。

<?xml version="1.0" encoding="UTF-8"?>
	<beans xmlns="http://www.springframework.org/schema/beans"
	    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	    xmlns:context="http://www.springframework.org/schema/context"
	    xsi:schemaLocation="http://www.springframework.org/schema/beans
	        https://www.springframework.org/schema/beans/spring-beans.xsd
	        http://www.springframework.org/schema/context
	        https://www.springframework.org/schema/context/spring-context.xsd">

	<context:component-scan base-package="SpringTest/commons/config"></context:component-scan>
	
	<!-- 基於XML的配置 -->

	</beans>
@Configuration
public class SpringConfig {
	//...基於Java的配置
}

ApplicationContext context = new ClassPathXmlApplicationContext("SpringTest/commons/config/beans.xml");

5.大融合

剩下的一點,就是基於註解的配置了。

讀到這裏,應該自己就可以想到,只要加上包掃描,就可以找到註解的配置。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章