Bean的配置方法(用法)

前一篇文章提到,有三个重要的方法把配置元数据提供给 Spring 容器。

一、基于XML配置

1.1 构造函数注入

当容器调用带有一组参数的类构造函数时,基于构造函数的 DI 就完成了,其中每个参数代表一个对其他类的依赖。

TextEditor 类

package com.tutorialspoint;

public class TextEditor {
   private SpellChecker spellChecker;
   public TextEditor(SpellChecker spellChecker) {
      System.out.println("Inside TextEditor constructor." );
      this.spellChecker = spellChecker;
   }
   public void spellCheck() {
      spellChecker.checkSpelling();
   }
}

SpellChecker 依赖类:

package com.tutorialspoint;

public class SpellChecker {
   public SpellChecker(){
      System.out.println("Inside SpellChecker constructor." );
   }
   public void checkSpelling() {
      System.out.println("Inside checkSpelling." );
   } 
}

配置文件 Beans.xml 的内容,它有基于构造函数注入的配置:





   
   
      
   

   
   
   

1.2 setter方法注入

当容器调用一个无参的构造函数或一个无参的静态 factory 方法来初始化你的 bean 后,通过容器在你的 bean 上调用设值函数,基于设值函数的 DI 就完成了。

TextEditor 类

package com.tutorialspoint;

public class TextEditor {
   private SpellChecker spellChecker;
   // a setter method to inject the dependency.
   public void setSpellChecker(SpellChecker spellChecker) {
      System.out.println("Inside setSpellChecker." );
      this.spellChecker = spellChecker;
   }
   // a getter method to return spellChecker
   public SpellChecker getSpellChecker() {
      return spellChecker;
   }
   public void spellCheck() {
      spellChecker.checkSpelling();
   }
}

SpellChecker 依赖类:

package com.tutorialspoint;

public class SpellChecker {
   public SpellChecker(){
      System.out.println("Inside SpellChecker constructor." );
   }
   public void checkSpelling() {
      System.out.println("Inside checkSpelling." );
   }  
}

配置文件 Beans.xml 的内容,该文件有基于设值函数注入的配置:





   
   
      
   

   
   
   

1.3 自动装配

Spring 容器可以在不使用 constructor-arg 和 property 元素的情况下自动装配相互协作的 bean 之间的关系,这有助于减少编写一个大的基于 Spring 的应用程序的 XML 配置的数量。

下列自动装配模式,它们可用于指示 Spring 容器为来使用自动装配进行依赖注入。你可以使用 元素的 autowire 属性为一个 bean 定义指定自动装配模式。

模式 描述
no 这是默认的设置,它意味着没有自动装配,你应该使用显式的bean引用来连线。你不用为了连线做特殊的事。在依赖注入章节你已经看到这个了。
byName 由属性名自动装配。Spring 容器看到在 XML 配置文件中 bean 的自动装配的属性设置为 byName。然后尝试匹配,并且将它的属性与在配置文件中被定义为相同名称的 beans 的属性进行连接。
byType 由属性数据类型自动装配。Spring 容器看到在 XML 配置文件中 bean 的自动装配的属性设置为 byType。然后如果它的类型匹配配置文件中的一个确切的 bean 名称,它将尝试匹配和连接属性的类型。如果存在不止一个这样的 bean,则一个致命的异常将会被抛出。
constructor 类似于 byType,但该类型适用于构造函数参数类型。如果在容器中没有一个构造函数参数类型的 bean,则一个致命错误将会发生。
autodetect Spring首先尝试通过 constructor 使用自动装配来连接,如果它不执行,Spring 尝试通过 byType 来自动装配。

可以使用 byType 或者 constructor 自动装配模式来连接数组和其他类型的集合。

由构造函数自动装配:


    

由setter方法自动装配:



    






二、基于注解配置

Spring 2.5 后提供了一个context的命名空间,它提供了通过扫描类包来加载利用注解定义的Bean的方式。


                
                

Spring3.0提供了一系列的针对依赖注入的注解,这使得Spring IoC在XML文件之外多了一种可行的选择,主要包含如下注解类型:

  • Bean的定义注解
  • Bean的生命周期注解
  • Bean的依赖检查注解
  • Bean的自动装配注解

2.1 Bean的定义注解

Spring自2.0开始,陆续引入了一些注解用于简化Spring的开发。

@Repository注解便属于最先引入的一批,用于将数据访问层(DAO层)的类标识为Spring Bean。
如此的话,我们便不在需要在XML当中显式使用bean来进行bean的配置。Spring容器在初始化的时候便会自动扫描base-package所指定的包以及子包下面的所有class文件。所有标注为Repository的类将被自动注册为bean。

为什么Repository只能标注在DAO类上面呢?

       因为该注解的作用不只是将类识别为bean,同时他还能将所标注的类中所抛出的数据访问异常封装为Spring的数据访问异常类型。Spring本身提供了一个丰富的,并且是与具体的访问技术无关的数据访问异常结构,用于封装不同的持久层框架所抛出的异常,使得异常独立与底层的框架。

Spring2.5在@Repository的基础上增加了功能类似的额外三个注解,总共有如下四种注解:

  • @Component:一个泛化的概念,表示一个组件(Bean),可作用在任何层次
  • @Controller:用于对Controller实现类进行标注,目前该功能与Component相同
  • @Repository:用于对DAO实现类进行标注
  • @Service:用于对Service实现类进行标注,目前该功能与Component相同

这三个注解除了作用于不同软件层次的类,其使用方式与Repository是完全相同的。

2.2 Bean的生命周期注解

在某些情况下,可能需要我们手工做一些额外的初始化或者销毁操作,例如资源的获取和是否操作,Spring1.x为此提供了两种方式供用户指定执行生命周期回调的方法:

实现Spring提供的两个接口:initializingBean 和 DisposableBean,这种方法是要求bean类实现Spring的接口,但增加了bean和Spring容器的耦合度,因此不推荐使用。
在XML文件中使用的init-method 和 destory-method 属性,指定初始化之后和回调之前的回调方法。这两个属性的取值是bean中相应的初始化和销毁方法的名称。方法名称任意,但是方法不能有参数。
示例如下:


在这里,我们指定了userService 这个bean的初始化方法为:init     销毁方法为:destory

Spring2.5在保留以上两种方式的基础上,提供了对JSR-250的支持。

JSR-250规范定义了两个用于指定声明周期方法的注解:

  • @PostConstruct:初始化之后的执行的回调方法
  • @PreDestroy:销毁之前的回调方法

2.3 Bean的依赖检查注解

Spring2.0之前使用dependency-check在配置文件中设置属性用于依赖检查(只会检查Setter方法是否被调用),缺点是粒度较粗,该属性的取值包括以下几种:

  • none: 默认不执行依赖检查
  • simple :对原始基本类型和集合类型进行检查
  • objects :对复杂类型进行检查
  • all :对所有类型进行检查

使用Spring2.0提供的@Required注解,提供了更细粒度的控制,@Required注解只能标注在Setter方法之上,(标注在其他方法之上会被忽略 )用于检查其是否被调用,当Setter方法未被调用的话会抛出异常。

2.4 Bean的自动装配注解

 元素还会自动注册 AutowiredAnnotationBeanPostProcessor 实例, 该实例可以自动装配具有 @Autowired 和 @Resource 、@Inject注解的属性。

序号 注解 & 描述
1 @Required

@Required 注解应用于 bean 属性的 setter 方法。

2 @Autowired

@Autowired 注解可以应用到 bean 属性的 setter 方法,非 setter 方法,构造函数和属性。

3 @Qualifier

通过指定确切的将被连线的 bean,@Autowired 和 @Qualifier 注解可以用来删除混乱。

4 JSR-250 Annotations

Spring 支持 JSR-250 的基础的注解,其中包括了 @Resource,@PostConstruct 和 @PreDestroy 注解。

 @Autowired 注解自动装配具有兼容类型的单个 Bean属性

  • 构造器, 普通字段(即使是非 public), 一切具有参数的方法都可以应用@Authwired 注解
  • 默认情况下, 所有使用 @Authwired 注解的属性都需要被设置. 当 Spring 找不到匹配的 Bean 装配属性时, 会抛出异常, 若某一属性允许不被设置, 可以设置 @Authwired 注解的 required 属性为 false
  • 默认情况下, 当 IOC 容器里存在多个类型兼容的 Bean 时, 通过类型的自动装配将无法工作. 此时可以在 @Qualifier 注解里提供 Bean 的名称. Spring 允许对方法的入参标注 @Qualifiter 已指定注入 Bean 的名称
  • @Authwired 注解也可以应用在数组类型的属性上, 此时 Spring 将会把所有匹配的 Bean 进行自动装配.
  • @Authwired 注解也可以应用在集合属性上, 此时 Spring 读取该集合的类型信息, 然后自动装配所有与之兼容的 Bean.
  • @Authwired 注解用在 java.util.Map 上时, 若该 Map 的键值为 String, 那么 Spring 将自动装配与之 Map 值类型兼容的 Bean, 此时 Bean 的名称作为键值

三、基于Java容器配置 

从Spring 3.0开始,可以使用java代码配置Bean,替代XML配置。
首先让我们看一下基于Java类如何定义Bean配置元数据,具体步骤如下:

  1. 使用@Configuration注解需要作为配置的类,表示该类将定义Bean的元数据
  2. 使用@Bean注解相应的方法,该方法名默认就是Bean的名称,该方法返回值就是Bean的对象。
  3. AnnotationConfigApplicationContext或子类进行加载基于java类的配置

通过@Configuration注解的类将被作为配置类使用,表示在该类中将定义Bean配置元数据,且使用@Configuration注解的类本身也是一个Bean,使用方式如下所示:

@Configuration("ctxConfig")
public class ApplicationContextConfig {
    ……
}

其中Configuration中的参数值即为该bean的名称。
通过@Bean注解配置类中的相应方法,则该方法名默认就是Bean名,该方法返回值就是Bean对象,并定义了Spring IoC容器如何实例化、自动装配、初始化Bean逻辑,具体使用方法如下:

@Bean(name={},
      autowire=Autowire.NO,
      initMethod="",
      destroyMethod="")

其中name为bean的名称,可以有多个,autowire为是否自动装配,默认值为NO,initMethod为bean的初始化方法,destoryMethod为bean的销毁方法。

注意:使用bean注解的方法不能是private、final、static的。

基于Java方式的配置方式不是为了完全替代基于XML方式的配置,两者可以结合使用,因此可以有两种结合使用方式:

在基于Java方式的配置类中引入基于XML方式的配置文件
在基于XML方式的配置文件中中引入基于Java方式的配置
引入基于XML配置文件:


    
@Configuration("ctxConfig")
@ImportResource("classpath:com/jike/***/appCtx.xml")
public class ApplicationContextConfig {
  ……
}

可以看到在java程序中使用@ImportResource导入了XML的配置文件。

可以通过代码一个个的引入配置类,当然也可以使用@Import注解来引入配置类
引入多个配置类:

@Configuration
@Import(DaoConfig.class)
public class ServiceConfig  {……}

四、总结:不同配置方式比较

其实Spring支持这么多的配置方式,那么这些配置方式必然有其自己独特的舞台

  • 基于XML的配置主要使用场景:

第三方类库,如DataSource、JdbcTemplate等;
命名空间,如aop、context等;

  • 基于注解的配置主要使用场景:

Bean的实现类是当前项目开发的,可直接在Java类中使用注解配置

  • 基于Java类的配置主要使用场景:

对于实例化Bean的逻辑比较复杂,则比较适合用基于Java类配置的方式
在日常的开发中我们主要是使用XML配置和注解配置方式向结合的开发方式,一般不推荐使用基于Java类的配置方式。

你可能感兴趣的:(Spring,Framework)