Spring之基于注解的配置

作者:lvmingyin     分类:JAVA技术     时间:2014-06-05     浏览:52     评论:0 来源:博客园

  首先使用注解需要在spring配置文件中添加配置项

  <context:annotation-config />

 

  @Autowired 自动装配属性

    @Autowired不仅可以标注在set方法和属性上,甚至可以标注在需要自动装配Bean引用的任意方法上(也包括构造函数)。

    @Autowired不会受private关键字的影响,即使是私有的变量,它任然可以被装配。当使用了@Autowired注解时,Spring就会尝试对该方法或属性执行byType自动装配。

    但是,有两种情况下,@Autowired注解会受到影响,应用中只能有一个Bean适合装配到@Autowired注解所标注的属性或参数中。如果没有匹配的Bean,或者存在多个匹配的Bean,@Autowired就会注入失败。

    解决办法:默认情况下,@Autowired具有强契约特征,其所标注的属性或参数必须是可装配的。如果没有Bean可以装配到@Autowired所标注的属性或参数中,自动装配就会失败,抛出NoSuchBeanDefinitionException,但属性不一定必须要装配,NULL值也可以接受。在这种情况下,可以通过设置@Autowired的required属性为false来配置自动装配是可选的。例如

      @Autowired(required=false)

    这种情况下,Spring会尝试装配所标注的属性或参数,但是如果没有找到与之匹配的Bean时,应用程序就不会发生任何问题,所标注的属性值就会为NULL,required属性可以用于@Autowired注解所使用的任何地方。但当使用构造器装配时,只有一个构造器可以将@Autowired的required的属性设置为true。其他使用@Autowired注解所标注的构造方法只能将required属性设置为false。此外,当使用@Autowired标注多个构造器的时候,Spring就会从所有满足装配条件的构造器中选择入参最多的构造器。

    另一方面,问题在于或许spring并不缺少适合自动装配的Bean,可能会有多个适合装配的Bean。@Autowired没有办法选择哪一个Bean才是真正需要装配的,所以会抛出NoSuchBeanDefinitionException异常,表明装配失败了。

    为了帮助@Autowired鉴别哪一个Bean才是我们需要的,可以配合使用@Qualifier注解。例如

      @Autowired

      @Qualifier(name="beanId")

    @Qualifier注解将尝试注入name属性中指定名称的Bean。

    

    既然可以使用注解为Spring的Bean自动装配其他Bean的引用,同样可以使用注解来装配简单的值。Spring3.0引入了@Value,它是一个新的装配注解,可以让我们使用注解装配String类型的值和基本类型的值,例如int、boolean。我们可以通过@Value直接标注某个属性、方法或者方法参数,并传入一个String类型的表达式来装配属性。例如
    @Value("lvmingyin")
    private String name;
    但是,这些值我们通常可以直接在Java代码中编写,为什么还要在@Value的属性中设置呢,在这种情况下,@Value显得有些多余。
    实际上,装配简单的值并不是@Value所擅长的,借助SpEL表达式,@Value被赋予了魔力,在运行时通过SpEL动态计算复杂的表达式的值并把结果装配到Bean的属性中。这一特性也使得@Value注解称为强大的装配可选方案。
    例如,与其设置一个硬编码的静态值,不如使用SpEL从系统属性中获取一个值:
    @Value("#{systemProperties.myFavoritesSong}")
    private String song;

    在Spring配置中增加<context:annotation-config/>时能够有助于消除配置文件中的<property/>,但还是需要在配置文件中使用<bean>元素显式定义Bean。
    在Spring中海油一种技巧。<context:component-scan />元素除了完成和<context:annotation-config />一样的工作,还允许自动检测Bean和定义Bean。这以为着不使用<bean>元素,Spring应用中大多数Bean都能够实现定义和装配。
    为了配置Spring自动检测,需要使用<context:component-scan />元素来代替<context:annotation-config />元素。

    

    <context:component-scan base-package="com.lmy.spring"></context:component-scan>

    

    <context:component-scan />元素会扫描指定的包及其所有子包,并查找出能够自动注册为Spring Bean的类。base-package属性标识了<context:component-scan />元素所扫描的包。
    默认情况下,<context:component-scan />查找使用构造型(stereotype)注解所标注的类,这些特殊的注解如下:
      @Component---通用的构造型注解,标识该类为Spring组件。
      @Controller---标识该类定义为Spring MVC controller。
      @Repository---标识将该类定义为数据仓库。
      @Service---标识将该类定义为服务
    例如,需要声明一个Bean。可以配置<context:component-scan />元素并使用@Component注解标识这个类,从而消除显式的<bean/>定义
      package com.lmy.spring;
      @Component
      public class Dog{}
    Spring扫描com.lmy.spring包时,会发现使用@Component注解所标注的Dog,并自动地把它注册为Spring Bean。Bean的ID默认为无限定类名。在这种情况下,Dog Bean的ID为dog。
    还可以指定@Component注解的参数显式的指定Bean的ID。
      @Component("kala")
      public class Dog{}
      来声明一个ID为kala类型为Dog的Bean。

    还可以通过配置<context:include-filter />或者<context:exclude-filter/>调整扫描行为。如下所示:
      

<context:component-scan base-package="com.lmy.spring">
      <context:include-filter type="assignable" expression="com.lmy.spring.Animal" />
</context:component-scan>


    <context:include-filter />的type和expression属性一起协作来定义组件扫描策略。在这种情况下,我们要求派生于Animal的所有类自动注册为Spring Bean。我们还可以选择如下任意一种过滤器:
      annotation:过滤器扫描使用注解所标注的那些类,通过expression属性指定要扫描的注解。
      assignable:过滤器扫描派生于expression属性所指定类型的那些类。
      aspectj:过滤器扫描与expression属性所指定的AspectJ表达式所匹配的那些类。
      custom:使用自定义的org.springframework.core.type.TypeFilter实现类,该类由expression属性指定。
      regex:过滤器扫描类的名称与expression属性所指定的正则表达式所匹配的那些类。
    除了使用<context:include-filter />告知<context:component-scan/>哪些类需要注册为Spring Bean以外,我们还可以使用<context:exclude-filter />来告知 <context:component-scan/>哪些类不需要注册为Spring Bean。
    例如除了使用自定义注解@SkipIt的类,其他所有的Animal实现都要注册为Spring Bean

<context:component-scan base-package="com.lmy.spring">
<context:include-filter type="assignable" expression="com.lmy.spring.Animal" />
<context:exclude-filter type="annotation" expression="com.lmy.spring.SkipIt" />
</context:component-scan>

    除了使用注解以外,还有一种基于Java的配置,主要是使用@Configuration和@Bean来完成声明的

    在类上使用@Configuration标识告诉Spring,这个类包含一个或多个Spring Bean的定义。

    

    

@Configuration
public
class AnimalFactory{       //使用@Bean标识一个方法       @Bean       public Dog kala(){         return new Dog();       } }

  这个方法就是Java配置,他等价于XML所配置的<bean>元素。@Bean告知Spring这个方法返回一个对象,该对象应该被注册在Spring上下文中的一个Bean。方法名是这个Bean的ID。在该方法中实现的所有逻辑本质上都是为了创建Bean。

  配置完成了,如何使用基于Java的配置注入呢。很简单,先声明一个xiaohuang Bean。

  

@Bean
public Dog xiaohuang(){
  return new Dog("小黄");      
}

然后创建一个Person Bean,通过构造器为他装配xiaohuang。

@Bean
public Person zhuren(){
  return new Person(xiaohuang());  
}

通过引用其他Bean的方法来装配Bean的引用,虽然看起来简单,但是实际上发生的远远超过你的想象。

在Spring Java配置中,通过声明方法引用一个Bean并不等同于调用该方法。如果真的这样,每次调用xiaohuang,返回的都是一个新的实例。

通过使用@Bean注解标识xiaohuang()方法,会告诉Spring我们希望该方法定义的Bean要被注册进Spring应用上下文中。因此,在其他Bean的声明方法中引用这个方法时,Spring 都会拦截该方法的调用,并尝试在应用上下文中查找该Bean,而不是创建一个新的实例。

 

 

    

 

本文转载自:http://www.cnblogs.com/lvmingyin/p/3566906.html

上一篇:用重绘的滚动条控制ListBox的滚动

下一篇:继续寻找app开发的技术方案


0 评论

查看所有评论

给个评论吧