Spring 3 增加的 @Configuration 和 @Bean

@Configuration 和 @Bean 

虽然 2.0 版本发布以来,Spring 陆续提供了十多个注解,但是提供的这些注解只是为了在某些情况下简化 XML 的配置,并非要取代 XML 配置方式。这一点可以从 Spring IoC 容器的初始化类可以看出:

ApplicationContext 接口的最常用的实现类是 ClassPathXmlApplicationContextFileSystemXmlApplicationContext,以及面向 Portlet 的 XmlPortletApplicationContext 和面向 web 的 XmlWebApplicationContext,它们都是面向 XML 的。

Spring 3.0 新增了另外两个实现类:AnnotationConfigApplicationContextAnnotationConfigWebApplicationContext。从名字便可以看出,它们是为注解而生,直接依赖于注解作为容器配置信息来源的 IoC 容器初始化类。

由于 AnnotationConfigWebApplicationContext 是 AnnotationConfigApplicationContext 的 web 版本,其用法与后者相比几乎没有什么差别,因此本文将以 AnnotationConfigApplicationContext 为例进行讲解。


AnnotationConfigApplicationContext 搭配上 @Configuration 和 @Bean 注解,自此,XML 配置方式不再是 Spring IoC 容器的唯一配置方式。两者在一定范围内存在着竞争的关系,但是它们在大多数情况下还是相互协作的关系,两者的结合使得 Spring IoC 容器的配置更简单,更强大。

 

 

之前,我们将配置信息集中写在 XML 中,如今使用注解,配置信息的载体由 XML 文件转移到了 Java 类中。我们通常将用于存放配置信息的类的类名以 “Config” 结尾,比如 AppDaoConfig.java、AppServiceConfig.java 等等。我们需要在用于指定配置信息的类上加上 @Configuration 注解,以明确指出该类是 Bean 配置的信息源。

 

 

 

Spring 对标注 Configuration 的类有如下要求:

  • 配置类不能是 final 的;

  • 配置类不能是本地化的,亦即不能将配置类定义在其他类的方法内部;

  • 配置类必须有一个无参构造函数。

AnnotationConfigApplicationContext 将配置类中标注了 @Bean 的方法的返回值识别为 Spring Bean,并注册到容器中,受 IoC 容器管理。@Bean 的作用等价于 XML 配置中的 <bean/> 标签。示例如下:

@Configuration 
public class BookStoreDaoConfig{ 
   @Bean 
   public UserDao userDao(){
         return new UserDaoImpl();
} 

   @Bean 
   public BookDao bookDao(){
         return new BookDaoImpl();
} 

}


Spring 在解析到以上文件时,将识别出标注 @Bean 的所有方法,执行之,并将方法的返回值 ( 这里是 UserDaoImpl 和 BookDaoImpl 对象 ) 注册到 IoC 容器中。默认情况下,Bean 的名字即为方法名。因此,与以上配置等价的 XML 配置如下:

 

<bean id=”userDao” class=”bookstore.dao.UserDaoImpl”/> 
<bean id=”bookDao” class=”bookstore.dao.BookDaoImpl”/>

 

@Bean 具有以下四个属性:

  • name -- 指定一个或者多个 Bean 的名字。这等价于 XML 配置中 <bean> 的 name 属性。

  • initMethod -- 容器在初始化完 Bean 之后,会调用该属性指定的方法。这等价于 XML 配置中 <bean> 的 init-method 属性。

  • destroyMethod -- 该属性与 initMethod 功能相似,在容器销毁 Bean 之前,会调用该属性指定的方法。这等价于 XML 配置中 <bean> 的 destroy-method 属性。

  • autowire -- 指定 Bean 属性的自动装配策略,取值是 Autowire 类型的三个静态属性。Autowire.BY_NAME,Autowire.BY_TYPE,Autowire.NO。与 XML 配置中的 autowire 属性的取值相比,这里少了 constructor,这是因为 constructor 在这里已经没有意义了。

@Bean 没有直接提供指定作用域的属性,可以通过 @Scope 来实现该功能,关于 @Scope 的用法:基于 Spring 2.5 的常用注释

 

 

基于注解的容器初始化

 

AnnotationConfigApplicationContext 提供了三个构造函数用于初始化容器:

  • AnnotationConfigApplicationContext():该构造函数初始化一个空容器,容器不包含任何 Bean 信息,需要在稍后通过调用其 register() 方法注册配置类,并调用 refresh() 方法刷新容器。

  • AnnotationConfigApplicationContext(Class<?>... annotatedClasses):这是最常用的构造函数,通过将涉及到的配置类传递给该构造函数,以实现将相应配置类中的 Bean 自动注册到容器中。

  • AnnotationConfigApplicationContext(String... basePackages):该构造函数会自动扫描以给定的包及其子包下的所有类,并自动识别所有的 Spring Bean,将其注册到容器中。它不但识别标注 @Configuration 的配置类并正确解析,而且同样能识别使用 @Repository、@Service、@Controller、@Component 标注的类。

除了使用上面第三种类型的构造函数让容器自动扫描 Bean 的配置信息以外,AnnotationConfigApplicationContext 还提供了 scan() 方法,其功能与上面也类似,该方法主要用在容器初始化之后动态增加 Bean 至容器中。调用了该方法以后,通常需要立即手动调用 refresh() 刷新容器,以让变更立即生效。

 

需要注意的是,AnnotationConfigApplicationContext 在解析配置类时,会将配置类自身注册为一个 Bean,因为 @Configuration 注解本身定义时被 @Component 标注了。因此可以说,一个 @Configuration 同时也是一个 @Component。大多数情况下,开发者用不到该 Bean,并且在理想情况下,该 Bean 应该是对开发者透明的。

 

@Configuration 的源码定义如下所示:

@Target({ElementType.TYPE}) 
@Retention(RetentionPolicy.RUNTIME) 
@Documented 
@Component 
public @interface Configuration { 
String value() default ""; 
}

 


在一般的项目中,为了结构清晰,通常会根据软件的模块或者结构定义多个 XML 配置文件,然后再定义一个入口的配置文件,该文件使用 <import/> 将其他的配置文件组织起来。最后只需将该文件传给 ClassPathXmlApplicationContext 的构造函数即可。针对基于注解的配置,Spring 也提供了类似的功能,只需定义一个入口配置类,并在该类上使用 @Import 注解引入其他的配置类即可,最后只需要将该入口类传递给 AnnotationConfigApplicationContext。具体示例如下:

 

 

@Configuration 
@Import({BookStoreServiceConfig.class,BookStoreDaoConfig.class}) 
public class BookStoreConfig{ … }

 

转载自:

https://www.ibm.com/developerworks/cn/opensource/os-cn-spring-iocannt/

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值