基于注解自动装配Bean

      自动装配(autowiring):有助于减少<property>和<constructor-arg>,让spring自动识别如何装配Bean的依赖关系。

      自动检测(autodiscovery):让spring自动识别那个类要被装配成spring Bean,减少对<bean>元素的使用。


1.自动装配Bean属性

     

1.1    4中类型的自动装配

      1.byName:把与Bean的属性具有相同名字(或者ID)的其他Bean自动装配到Bean的对应属性中。如果没有与属性的名字相匹配的Bean,则该属性不进行装配。

      2.byType:把与Bean的属性具有相同类型的其他Bean自动装配到Bean的对应属性中。如果没有与属性的类型相匹配的Bean,则该属性不进行装配。

      3.constructor:把与Bean的构造器入参具有相同类型的其他Bean自动装配到Bean构造器的对应入参中。

      4.autodetect:先按constructor来装配,失败了按byType来装配。


1.1.1  byName自动装配

 

<bean id="aaa" clas=""/>
<bean id="bbb" class="" >
   <property name="aaa" ref="aaa"/>
</bean>

如果bbb中aaa属性名字和Bean的id相同,则可以自动装配。如果bean的id和property的name相同,那么可以变为下面的这种方式:

<bean id="aaa" clas=""/>
<bean id="bbb" class="" autowire="byName">
 
</bean>

如果一个Bean中属性和其他Bean的id相同就会自动装配,可是自己不需要自动装配。byName的缺点就是要假设属性名和Bean的id要一样。


1.1.2  byType自动装配

      跟byName一样,只是ByType不去找属性名一样,而是去找属性的类型。

<bean id="aaa" clas="A"/>
<bean id="bbb" class="" >
   <property name="aaa" ref="aaa"/>
</bean>
如果bbb中属性aaa为A类型,则可以byType自动装配,把autowire="byType"

<bean id="aaa" clas="A"/>
<bean id="bbb" class="" autowire="ByType">
   
</bean>
      如果byType找到多个Bean,那么抛出异常,应用只允许存在一个Bean与需要的自动装配的属性相匹配。byName不会找到多个,因为Bean的id是不一样的。解决的办法就是可以标识一个首选Bean,也可以让其他Bean失去资格。<bean>元素有个primary属性表示首选Bean,但是默认为true,所有的Bean都是首选Bean,所以要把非首选的Bean设置为false。<bean>的

autowire-candidate属性可以设置为false表示自动装备忽略Bean的资格。


1.1.3 constructor自动装配

      不需要<constructor-arg>元素,autowire为constructor。和byType有相同的局限性,也是按照类型去匹配的,一个构造器参数对应多个Bean,还有一个Bean对应多个构造器。

      


1.2 默认自动装配

      如果所有的bean都按照同一类型自动装配,可以再<beans>元素中加default-autowire属性。这个属性默认为none,表示不使用自动装配。可以设置为byName等类型。<bean>中的autowire会覆盖default-autowire属性。<property>会覆盖自动装配的值。

      autowire=“constructor”时,不能与<constructor-arg>同时存在。其他类型可以于<property>同时存在。

      

2.  使用注解装配

      spring容器是默认禁用注解装配的。要启动,最简单的就是context命名空间的<context:annotation-config/>

      1.spring自带的@Autowired注解

      2.JSR-330的@Inject注解

      3.JSR-250的@Resource注解



2.1 @Autowired

      有了这个注解,spring会按byType自动装配。这个注解可以加在setter方法上,还可以加在需要自动装配Bean的任意方法上,还可以加在构造器上。这个注解可以直接加在属性上,并删除setter方法。

       这个注解必须只能有一个Bean匹配到注解的参数或属性中。没有匹配Bean或匹配多个Bean会有问题。

2.1.1可选的自动装配

       默认情况下,这个注解标识的属性或参数必须是可装配的。没有Bean装配到,就会报NoSuchBeanDefinitionException。这个时候可以设置required=false来设置自动装配是可选的。没有匹配到Bean就会为null。

@Autowired(required=false)
private A a;
       required可以用于@Autowired使用的任何地方,但是在构造器中,只能有一个构造器是required为true,其他都要设置为false。当@Autowired标注多个构造器时,spring会从满足条件的构造器中选择入参最多的构造器。


2.1.2限定歧义性的依赖
        有可能spring找到了多个满足条件的Bean,可以使用@Qualifier注解。

@Autowired
@Qualifier("a")//指定a,默认从id找
private A a;
        相当于把byType转为了byName。缩小了自动装配Bean的范围。还可以在Bean中声明

<bean class="A">
      <qualifier value="a"/>//可以限定这个Bean为a
</bean>
@Qualifier("a")//可以限定这个Bean为a
class A implement B{}
        @Autowired是减少spring xml配置的一种方式。但是使用它的类会引入spring的特定依赖。


2.2 @Inject
       

@Inject
private A a;
       这个注解和@Autowired一样可以自动装配,可以装配属性,方法,构造器。但是没有required属性所以装配的Bean必须存在,不存在会报错。

       
2.2.1限定@Inject所标注的属性

       @Autowired的@Qualifier与@Inject的@Named对应

@Inject
@Named("a")
private A a;
      @Qualifier注解缩小Bean的选择范围(默认使用Bean的id),@Named通过Bean的Id标识可选择的Bean。

2.3在注解注入中使用表达式

        @Value可以装配简单值。

@Value("jack")//这里面是一个表达式
private String name;
@Value("#{abc.name}")
private String name;

2.4@Resource

@Resource装配顺序
  1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
  2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
  3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
  4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;


3.自动检测Bean

       <context:component-scan>除了完成<context:annotation-config>一样的工作外,还允许Spring自动检测Bean和定义Bean。

<context:component-scan//替代了<context:annotation-config>
base-package="包">//会扫描指定的包及其子包,并找出能够自动注册的spring Bean
     
</context:component-scan>
        


3.1为自动检测标注Bean

      默认情况下<context:component-scan>查找使用构造型注解所标注的类。

      1.@Component:通用的构造型注解,表示该类为spring组件

      2.@Controller:表示该类定义为spring mvc controller

      3.@Repository:表示该类为数据仓库。

      4.@Service:表示该类定义为服务

      5.使用@Component标识的任意自定义注解
         

3.2过滤组件扫描

       <context:component-scan>下面还有子元素<context:include-filter>和<context:exclude-filter>。只是用<context:component-scan>的情况下,spring只会去找基于注解的组件。但是还要包含一个没有注解的接口的所有实现类要怎么办。就是用<context:include-filter>

<context:component-scan
base-package="包">
     <context:include-filter type="assignable" expression="xxx.abc"/>
</context:component-scan>
type的5中类型

1.annotation:扫面指定注解所标注的类,通过expression指定注解。

2.assignable:扫面派生于expression指定类型的哪些类。

3.aspectj:扫面与expression指定的aspectJ表达式匹配的类

4.custom:指定expression使用的自定义TypeFilter实现类。

5.regex:正则匹配的类。


4 使用spring基于Java的配置

      

4.1 创建基于Java的配置

      <context:component-scan>也会自动加载使用@Configuration注解所标注的类。

4.2 定义一个配置类

      @Configurstion标注的类相当于<Beans>元素。可以包含一个或多个Bean。这些Bean的定义是使用@Bean注解来标注的方法。

4.3 声明一个简单Bean

@Bean 
public A get(){
    return new B();
}
     @Bean告知spring返回一个对象,该对象应该被注册为spring上下文的一个Bean。方法名为Bean的id。
      相对于xml配置来说的一个优点就是,xml是用string类型配置的,编译期无法检查。如果重命名了一个类,或许会完了修改xml配置。

4.4 使用spring的基于Java的配置进行注入

 简单值注入:

@Bean
public A get(){
      return new B(12);
}
@Bean
public A get(){
      B b =  new B();
      b.setName("jack");
       return B;
}
引用注入:

@Bean
public A get(){
      return new B();
}
@Bean
public C set(){
      return new C(get());
}
这里调用get()不会调用get()方法而是调用spring上下文中的Bean。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值