Spring主要包括了三種配置bean元數據的方式:XML文件,java註解,java代碼。對於有代碼的潔癖的人說其實是一種折磨,因爲雖然希望能夠用上最新的配置方式,但是實際開發過程中可能用的是舊版本,或者一些第三方框架需要用到XML。雖然Spring一直推崇的是沒有侵入的框架,但是代碼很多地方難免要引入Spring依賴,不得不說是一種矛盾。吐槽完,我們還是要了解下這幾種配置方式的使用。
因爲Spring一開始就是XML配置方式,假設大家已經對此表示瞭解,這裏介紹後兩種方式,並且從後面Spring Boot的趨勢看也是基於java的會成爲主流。Spring 3.0後我們有了擺脫XML的可能。
@Configuration
@Configuration註解相當於之前的<beans/>
,這是一個類級的註解,用於配置bean的定義,該註解的類內部還可以有其他的@Configuration
@Bean
@Bean註解則相當於之前的<bean/>
,這是一個方法級的註解,用於定義一個bean,可以有@PostConstruct
,@PreDestroy
,也可以實現InitializingBean
, DisposableBean
, Lifecycle
接口添加生命週期的支持。
@Configuration
public class AppConfig {
@Bean(initMethod = "init")
@Scope("prototype")//作用域
public Foo foo() {
return new Foo();
}
@Bean(name = { "bar1", "subsystemA-bar"" })//別名
public Bar bar() {
return new Bar();
}
}
@Import
@Import相當於xml裏面的<import/>
,用於在配置類引入其他配置類,組合配置。
@Configuration
public class ConfigA {
@Bean
public A a() {
return new A();
}
}
@Configuration
@Import(ConfigA.class)
public class ConfigB {
@Bean
public B b() {
return new B();
}
}
AnnotationConfigApplicationContext
java配置類通過AnnotationConfigApplicationContext
初始化Spring容器,類似ClassPathXmlApplicationContext
加載XML配置文件的方式:
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
MyService myService = ctx.getBean(MyService.class);
myService.doStuff();
}
也可以直接初始化由@Component
或JSR-330註解的bean:
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(MyServiceImpl.class, Dependency1.class, Dependency2.class);
MyService myService = ctx.getBean(MyService.class);
myService.doStuff();
}
更簡單的是通過@ComponentScan
實現組件掃描,自動初始化容器:
@Configuration
@ComponentScan(basePackages = "com.acme")
public class AppConfig {
...
}
AnnotationConfigWebApplicationContext
AnnotationConfigWebApplicationContext
用於代替
XmlWebApplicationContext
配置Spring ContextLoaderListener和Spring
DispatcherServlet,在web.xml
中加入以下配置,替換原來的applicationContext.xml
:
<web-app>
<!-- 配置ContextLoaderListener使用AnnotationConfigWebApplicationContext -->
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<!-- Configuration類 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.acme.AppConfig</param-value>
</context-param>
<!-- 啓動application context -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Spring MVC DispatcherServlet -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 配置DispatcherServlet使用AnnotationConfigWebApplicationContext -->
<init-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</init-param>
<!-- Configuration類 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.acme.web.MvcConfig</param-value>
</init-param>
</servlet>
<!-- 映射/app/*到dispatcher servlet -->
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
</web-app>
在xml引入@Configuration註解的配置類
對於以前的系統大多是使用xml配置方式,我們可以把@Configuration註解的配置類當作一個bean引入到xml,從而實現註解方式的配置與原有的兼容。
<beans>
<!-- 啓用註解配置 -->
<context:annotation-config/>
<context:property-placeholder location="classpath:/com/acme/jdbc.properties"/>
<!-- 引入配置類 -->
<bean class="com.acme.AppConfig"/>
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
</beans>
在@Configuration配置類引入xml
如果想以註解方式爲主,則可以把原有的xml配置引入到@Configuration配置類:
@Configuration
@ImportResource("classpath:/com/acme/properties-config.xml")
public class AppConfig {
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean
public DataSource dataSource() {
return new DriverManagerDataSource(url, username, password);
}
}