spring基础(2:最小化XML配置)

一、自动装配

1、四种类型的自动装配

类型

解释

xml配置

byName

根据Bean的name或者id

<bean id="bean" class="…" autowire="byName"/>

ByType

根据Bean类型自动装配

<bean id="bean" class="…" autowire="byType"/>

contructor

根据Bean的构造器入参具有相同类型

同上

Autodetect

首先使用contructor,失败再尝试byType

同上

  byType在出现多个匹配项时不会自动选择一个然是报错,为避免报错,有两种办法:1.使用<bean>元素的primary属性,设置为首选Bean,但所有bean的默认primary都是true,因此我们需要将所有非首选Bean设置为false;2.将Bean的autowire-candidate熟悉设置为false ,取消 这个Bean的候选资格,这个Bean便不会自动注入了。

  contructor自动装配和byType有一样的局限性,当发现多个Bean匹配某个构造器入参时,Spring不会尝试选择其中一个;此外,如果一个类有多个构造器都满足自动装配的条件,Spring也不会猜测哪个更合适使用。

2、默认自动装配

  如果需要为Spring应用上下文中的每个Bean(或者其中的大多数)配置相同的autowire属性,可以在根元素<beans>上增加一个default-autowire属性,默认该属性设置为none。该属性只应用于指定配置文件中的所有Bean,并不是Spring上下文中的所有Bean。

3、混合使用自动装配和显式装配

  当我们对某个Bean使用了自动装配策略,并不代表我们不能对该Bean的某些属性进行显示装配,任然可以为任意一个属性配置<property>元素,显式装配将会覆盖自动装配。但是当使用constructor自动装配策略时,我们必须让Spring自动装配构造器所有入参,不能使用<constructor-arg>元素进行混合。

二、注解装配

  从Spring2.5开始,可以使用注解自动装配Bean的属性,使用注解允许更细粒度的自动装配,可选择性的标注某一个属性来对其应用自动装配。Spring容器默认禁用注解装配,需要在Spring配置中启用,最简单的启用方式是使用Spring的context命令空间配置中的<context:annotation-config>,如下所示:

<beans ...>
  <context:annotation-config/>
  <!-- bean declarations go here -->
</beans>

  Spring3支持几种不同的用于自动装配的注解:

  • Spring自带的@Autowired注解
  • JSR-330的@Inject注解
  • JSR-250的@Resource注解

1、使用@Autowired

  @Autowired用于对被注解对象启动ByType的自动装配,可用于以下对象:

  • 类属性,即使私有属性也能注入
  • set方法
  • 构造器
  • 任意需要装配Bean的方法

在使用@Autowired时有两种情况会出错:没有匹配的Bean和存在多个匹配的Bean,但是都有对应的解决方法。

  • 当没有匹配Bean时,自动装配会抛出NoSuchBeanDefinitionException,如果不想抛出可使用required属性,设置为false来配置可选的自动装配,即装配失败就不进行装配,不会报错。 @Autowired(required=false) 当使用构造器配置时,只有一个构造器可以将required属性设置为true,其他都只能设置为false。此外,当使用注解标注多个构造器时,Spring会从所有满足装配条件的构造器中选择入参最多的那个。
  • 当存在多个Bean满足装配条件时,Spring也会抛出NoSuchBeanDefinitionException错误,为了选择指定的Bean,我们可以使用@Qualifier注解进行筛选: @Autowired @Qualifier("name1")//筛选名为name1的Bean private TestClass testClass; 除了通过Bean的ID来缩小选择范围,我们还可以通过直接在Bean上使用qualifier来缩小范围,限制Bean的类型,xml如下: <bean class="com.test.xxx"> <qualifier value="stringed"/> </bean> 注解如下: @Qualifier("stringed") public class xxx{} 还可以创建自定义限定器(Qualifier)   创建自定义限定器只需要使用@Qualifier注解作为它的源注解即可,如下创建了一个Stringed限定器: @Target({ElementType.FIELD,ElementType.PARAMETER,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Qualifier public @interface Stringed{} 然后使用它注解一个Bean: @Stringed public class Guitar{} 然后就可以进行限定了: @Autowired @Stringed private Guitar guitar;

2、使用@Inject自动注入

  为统一各种依赖注入框架的编程模型,JCP(Java Community Process)发布的Java依赖注入规范,被称为JSR-330,从Spring3开始,Spring已经开始兼容该依赖注入模型。

  和@Autowired一样,@Inject可以用来自动装配属性、方法和构造器。但是@Inject没有required属性,因此依赖关系必须存在,如不存在将抛出异常。

  JSR-330还提供另一种注入技巧,注入一个Provider。Provider接口可以实现Bean引用的延迟注入以及注入Bean的多个实例等功能。

  例如我们有一个KnifeJuggler类需要注入一个或多个Knife实例,假设Knife Bean的作用域声明为prototype,下面的KnifeJuggler的构造器将获得多个Knife Bean:

private Set<Knife> knifes;

@Inject
public KnifeJuggler(Provider<Knife> knifeProvider){
    knives = new HashSet<Knife>();
    for(int i=0;i<5;i++){
        knives.add(knifeProvider.get());
    }
}

  相对于@Autowired所对应的@Qualifier,@Inject对应的是@Named注解。事实上JSR-330中也有@Qualifier注解,不过不建议直接使用,建议通过该注解来创建自定义的限定注解,和Spring的@Qualifier创建过程类似。

3、注解中使用表达式

  Spring3中引入的@Value属性可用来装配String类型的值和基本类型的值。借助SpEL表达式,@Value不光可以装配硬编码值还可以在运行期动态计算表达式并装配,例如下面的:

@Value("#{systemProperties.name}")
private String name;

三、自动检测Bean

  在Spring中使用上面说到的<context:annotation-config>,可以做到自动装配,但还是要在xml中申明Bean。Spring还有另一个元素<context:component-scan>,元素除了完成自动装配的功能,还允许Spring自动检测Bean和定义Bean ,用法如下:

<beans ...>
  <context:component-scan base-package="com.springtest">
  </context:component-scan>
</beans>

开启后支持如下注解:

注解

解释

@Component

通用的构造型注解,标识类为Spring组件

@Controller

标识该类定义为Spring MVC controller

@Repository

标识该类定义为数据仓库

@Service

标识该类定义为服务

  使用上述注解是Bean的ID默认为无限定类名。使用@Component("name")指定ID。

1、过滤组建扫描

  通过为配置和子元素,我们可以随意调整扫描行为。下面的配置自动注册所有的TestInterface实现类:

<context:component-scan base-package="com.fxb.springtest">
  <context:include-filter type="assignable"
      expression="com.fxb.springTest.TestInterface"/>
</context:component-scan>

其中的type和expression属性一起协作来定义组件扫描策略。type有以下值可选择:

过滤器类型

描述

annotation

过滤器扫描使用指定注解所标注的类。通过expression属性指定要扫描的注解

assignable

过滤器扫描派生于expression属性所指定类型的那些类

aspectj

过滤器扫描于expression属性所指定的AspectJ表达式所匹配的那些类

custom

使用自定义的org.springframework.core.type.TypeFilter实现类,该类由expression属性指定

regex

过滤器扫描类的名称与expression属性所指定的正则表达式所匹配的类

  exclude-filter使用和include-filter类似,只是效果相反。

四、使用Spring基于Java的配置

  在Spring3.0中几乎可以不使用XML而使用纯粹的Java代码来配置Spring应用。

  • 首先还是需要极少量的XML来启用Java配置,就是上面说到的<context:component-scan>,该标签还会自动加载使用@Configuration注解所标识的类
  • @Configuration注解相当于XML配置中的<beans>元素,这个注解将会告知Spring:这个类包含一个或多个Spring Bean的定义,这些定义是使用@Bean注解所标注的方法
  • 申明一个简单的Bean代码如下: @Configuration public class TestConfig{ @Bean public Animal duck(){ return new Ducker(); } } @Bean告知Spring这个方法将返回一个对象,该对象应该被注册为Spring应用上下文中的一个Bean,方法名作为该Bean的ID 。想要使用另一个Bean的引用也很简单,如下: @Bean public Food duckFood(){ return new DuckFood(); } @Bean //通过方法名引用一个Bean,并不会创建一个新的实例 public Animal duck(){ return new Ducker(DuckFood()); } 五、小结   终于写完了spring 的最小化配置,对spring的各种注解也有了一些了解,再不是之前看到注解一脸莫名其妙了,虽然现在Springboot已经帮我们做了零XML配置,但觉得还是有必要了解下XML配置实现,这样对Java的配置实现理解也会更加深刻。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏开发与安全

linux网络编程之System V 消息队列(一):消息队列内核结构和msgget、msgctl 函数

一、消息队列 1、消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法 2、每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值 ...

2330
来自专栏Java学习之路

07 Spring框架 依赖注入(四)基于注解的依赖注入

前面几节我们都在使用xml进行依赖的注入,但是在实际的开发中我们往往偏爱于使用注解进行依赖注入,因为这样更符合我们人的思维,并且更加快捷,本节就来讲述Sprin...

3787
来自专栏Jerry的SAP技术分享

MongoDB最简单的入门教程之五-通过Restful API访问MongoDB

通过前面四篇的学习,我们已经在本地安装了一个MongoDB数据库,并且通过一个简单的Spring boot应用的单元测试,插入了几条记录到MongoDB中,并通...

1601
来自专栏ImportSource

必须知道的Spring Boot中的一些Controller注解

本文旨在向你介绍在Spring Boot中controller中最基本的一些注解,不可能涵盖所有的,但至少让你了解最基本的,然后可以通过这些注解来写出一个API...

3.6K10
来自专栏老付的网络博客

SpringMVC 教程

   Spring 是目前比较流行的MVC框架,让POJO处理起来变的容易,也支持Rest的Url请求。采用松散的耦合可插拔的接口,比其它MVC接口更具有扩展...

1934
来自专栏玩转JavaEE

Spring常用配置

上篇文章我们简单介绍了Spring的基本配置,算是一个简单的入门,这篇文章我们再一起来看看Spring在使用的过程中一些其他的常见配置。 Bean的Scope ...

3296
来自专栏帅小子的日常

使用redis做缓存

8147
来自专栏IT 指南者专栏

Spring框架系列(二)之Bean的注解管理

微信公众号:compassblog 欢迎关注、转发,互相学习,共同进步! 有任何问题,请后台留言联系! 1、Spring中的两种容器 在系列(一)中我们已经知道...

3436
来自专栏java思维导图

Spring常用注解(收藏大全)

@Configuration 声明当前类为配置类,相当于xml形式的Spring配置(类上)

1342
来自专栏lgp20151222

@RequestParam与@PathVariable的区别

value:参数名字,即入参的请求参数名字,如username表示请求的参数区中的名字为username的参数的值将传入;

1392

扫码关注云+社区

领取腾讯云代金券