文章目錄
多個配置元數據的合併
在實際開發中,一般不會將所有的配置元數據放到同一個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.大融合
剩下的一點,就是基於註解的配置了。
讀到這裏,應該自己就可以想到,只要加上包掃描,就可以找到註解的配置。