您的位置:首页 > 编程语言 > Java开发

【Spring】【笔记】《Spring In Action》第3章 简化XML配置

2016-05-23 15:18 597 查看
自动装配 autowiring :让Spring自动识别如何装配Bean的依赖关系
自动检测 autodiscovery: 让Spring自动识别哪些类需要被配置成Spring Bean

3.1 自动装配Bean属性
3.1.1 4种类型的自动装配
byName:把与Bean的属性具有相同名字(或ID)的其他Bean自动装配到Bean的对应属性中。如果没有跟属性名字相匹配的Bean,不装配
byType:把与Bean的属性具有相同类型的其他Bean自动装配到Bean的对应属性中。如果没有跟属性类型相匹配的Bean,则该属性不装配
constructor:把与Bean的构造器入参具有相同类型的其他Bean自动装配到Bean构造器的对应入参中
autodetect:首先尝试使用constructor进行自动装配,如果失败再尝试使用byType进行自动装配

byName:
     约定为属性自动装配ID与该属性的名字相同的Bean
    
byType:
     Spring会去寻找哪一个Bean的类型与属性的类型相匹配。如果Spring找到了多个类型与需要自动装配的属性相匹配,Spring会抛出异常。为了避免使用byType自动装配而带来的歧义,Spring提供了两种选择:
为自动装配标识一个首选Bean

      标识首选Bean,可以使用<bean>元素的primary属性,如果只有一个自动装配的候选Bean的primary属性设置为true,那么该Bean将比其他候选Bean优先选择。*但是primary属性的默认值为true
取消某个Bean自动装配的候选资格

      取消候选资格可设置Bean的autowired-candidate属性为false

constructor:
     移除<constructor -arg>元素,设置<bean>的autowire的属性为constructor,具有与byType相同的局限性

autodetect:
     最佳自动装配

3.1.2 默认自动装配
     如果需要为Spring应用上下文中的每一个或大多数Bean配置相同的autowire的属性,那么可以设置一个自动的装配策略来简化设置。
     在根元素<beans>上增加一个default-autowired属性,默认为none
     <bean>元素的autowire属性会覆盖默认方式

3.1.3 混合使用自动装配和显式装配
     当使用constructor自动装配策略时,必须让Spring自动装配构造器的所有入参,不能混合使用constructor自动装配策略和<constructory -arg>元素

3.2 使用注解装配
     允许更细粒度的自动装配,可以选择性的标注某一属性来对其应用自动装配
     Springle容器默认禁用注解装配。在使用基于注解的自动装配前,需要在Spring的配置中启用

<context:annotation-config/>
     Spring支持集中不同的用于自动装配的注解:
Spring自带:@Autowired
JSR-330:@Injection
JSR-250:@Resource

3.2.1 使用@Autowired
     可标注在setter方法上,需要自动装配Bean引用的任意方法、构造器,也可直接标注在属性上,删除setter方法
     @Autowired不会受限于private
     受限的情况:存在0个或多个匹配的Bean

可选的自动装配:
     默认情况下,@Autowired具有强契约特征,其标注的属性或参数必须是可装配的。如果没有Bean可装配,会抛出NoSuchBeanDefinitionException。
     若null值是可以接受的,需要设置

@Autowired(required = false)
     当使用构造器装配时,只有一个构造器可以将@Autowired的required属性设置为true,其他使用@Autowired的注解所标注的构造器只能将required属性设置为false。
     当使用@Autowire的标注多个构造器,Spring会从所有满足装配条件的构造器中选择入参最多的构造器

限定歧义性的依赖
     @Qualifier 通过ByID的方式缩小候选Bean范围

创建自定义的限定器
     创建一个自定义的先顶起注解,需要定义一个注解,并使用@Qualifier注解作为它的元注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.beans.factory.annotation.Qualifier;

@Target({ElementType. FIELD,ElementType. PARAMETER,ElementType. TYPE})
@Retention (RetentionPolicy. RUNTIME)
@Qualifier
public @interface StringedInstrument {

}

     自定义的限定器可用来标注Bean,也可与@Autowired配合限定注入范围
     可使用多个自定义的限定器

3.2.2 借助@Inject实现基于标准的自动装配
     JCP发布,Java依赖注入规范,称为JSR-330
     @Inject是JSR-330的核心部件,几乎可以完全替代@Autowired
     @Inject没有required属性
     JSR-330提供了要求@Inject注入一个Provider;Provider几口可以实现Bean的延迟注入以及注入多个Bean实例

限定@Inject所标注的属性
     对应于@Autowired的@Qualifier,@Inject使用@named标识。区别在于@Qualifier注解缩小所匹配Bean的选择范围(默认使用Bean的ID),而@Named通过Bean的ID来标识可选择的Bean

创建自定义的JSR-300Qualifier
     JSR-300在javax.inject包里有自己的@Qualifier注解,但不建议使用。JSR-330鼓励使用该注解来创建自定义的限定器。
     实际上,@Named注解就是一个使用@Qualifier注解所标注的注解

3.2.3 在注解中使用表达式
     Spring 3引入@Value,可以让我们使用注解装配String类型的值和基本类型的值。
     使用@Value配合SpELl可以完成动态的求值计算装配

3.3 自动检测Bean
     <context:component-scan>元素除了完成与<context:annotation-config>一样的工作,还允许Spring自动检测Bean和定义Bean。这意味着不适用<bean>元素,Spring应用中的大多数Bean都能够实现定义和装配。
     为了配置Spring自动检测,需要使用<context:componet-scan>代替<context:annotaion-config>元素 

<context:component-scan base package="">
</context:component-scan>

     <context:component-scan>元素会扫描base-package属性标识的包及其所有子包,查找出能够自动注册为Spring Bean的类。

3.3.1 为自动检测标注Bean
     默认情况下,<context:componet-scan>查找使用构造型(stereotype)注解所标注的类,这些特殊的注解如下
@Component:通用的构造型注解,标识该类为Spring组件
@Controller:标识将该类定义为Spring MVC controller
@Repository:标识将该类定义为数据仓库
@Service:标识将该类定义为服务
使用@Component标注的任意自定义注解
     
3.3.2 过滤组件扫描
      通过为<context:component-scan>配置<context:include-filter>和/或<context:exclude-filter>子元素,可以调整扫描行为。

<context:component-scan base-package="">
     <context:include-filter type="" expression=""/>
     <context:exclude-filter type="" expression=""/>
</context:component-scan>

     自定义组件扫描方式
过滤器类型描述
annotation过滤器扫描使用指定注解所标注的那些类。通过expression属性指定要扫描的注解
assignable过滤器扫描派生于expression属性所指定类型的那些类
aspectj过滤扫描与expression属性所指定的AspectJ表达式所匹配的哪些类
custom使用自定义的org.springframework.core.type.TypeFilter实现类,该类由expression属性指定
regex过滤器扫描类的名称与expression属性所指定的正则表达式所匹配的那些类
3.4 使用Spring基于Java的配置
     意思就是,减少XML的配置

3.4.1 创建基于Java的配置
     即使使用Java配置,仍需要极少量的XML来启动java配置

<?xml version="1.0" encoding="TUF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:context="http://www.springframework.org/schema/context"
     xsi:schemaLocation="http://www.springframework.org/schema/context
         http://www.springframework.org/schema/beans/spring-beans-4.2.xsd          http://www.springframework.org/schema/context
        
http://www.springframework.org/schema/context/spring-context-4.2.xsd">
  
     <context:component-scan
          base-package=""/>
</beans>

3.4.2 定义一个配置类
     在基于Java的配置里使用@Configuration注解的Java类,相当于XML配置中的<beans>元素(根元素)。
     使用@Bean注解所标注的方法用来定义Bean。

3.4.3 Bean声明
e.g.:

@Bean
public Performer duke() {
     return new Juggler();
}

     方法名将作为该Bean的ID。
     XML配置方法中,Bean的类型和ID都是由String属性来标示,缺点是无法进行编译器的检查,这种配置方法可以在编译期就避免一些错误。

3.4.4 使用Spring的基于Java的配置进行注入
注入值 e.g.:

@Bean
public Performer duke15() {
     return new Juggler(15)
}

setter注入:

@Bean
public Performer kenny() {
     Instrumentalist kenny = new Instrumentalist();
     kenny.setSong("Jingle Bells");
     return kenny;
}

装配引用:

@Bean
private Poem sonnet29() {
     return new Sonnet29();
}
@Bean
public Performer poeticDuke() {
     return new PoeticJuggler(sonnet29());
}

     在Spring的Java配置中,通过声明方法引用一个Bean并不等同于调用该方法,这样会导致每次调用都产生一个新的实例。实际上,使用@Bean注解标注的方法,会告知Spring希望该方法中定义的Bean要被注册进Spring的应用上下文中。因此,在其他Bean的声明方法中引用这个方法时,Spring都会拦截该方法的调用,并尝试在应用上下文中查找该Bean,而不是创建一个新的实例。

第3章小节
     配置<context:annotation-config/>,使用@Autowired等进行注解装配
     配置<context:component-scan base package="">,使用@Component@Controller@Repository@Service等注解标注Bean
     使用@Configuration和@Bean进行基于Java的spring配置
     
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息