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);
}
}