基于注解自动装配Bean

╰+攻爆jí腚メ 2022-09-26 15:51 348阅读 0赞
  1. 自动装配(autowiring):有助于减少<property>和<constructor-arg>,让spring自动识别如何装配Bean的依赖关系。
  2. 自动检测(autodiscovery):让spring自动识别那个类要被装配成spring Bean,减少对<bean>元素的使用。

1.自动装配Bean属性

1.1 4中类型的自动装配

  1. 1.byName:把与Bean的属性具有相同名字(或者ID)的其他Bean自动装配到Bean的对应属性中。如果没有与属性的名字相匹配的Bean,则该属性不进行装配。
  2. 2.byType:把与Bean的属性具有相同类型的其他Bean自动装配到Bean的对应属性中。如果没有与属性的类型相匹配的Bean,则该属性不进行装配。
  3. 3.constructor:把与Bean的构造器入参具有相同类型的其他Bean自动装配到Bean构造器的对应入参中。
  4. 4.autodetect:先按constructor来装配,失败了按byType来装配。

1.1.1 byName自动装配

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

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

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

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

1.1.2 byType自动装配

  1. byName一样,只是ByType不去找属性名一样,而是去找属性的类型。
  2. <bean id="aaa" clas="A"/> <bean id="bbb" class="" > <property name="aaa" ref="aaa"/> </bean>

如果bbb中属性aaa为A类型,则可以byType自动装配,把autowire=”byType”

  1. <bean id="aaa" clas="A"/> <bean id="bbb" class="" autowire="ByType"> </bean>
  2. 如果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自动装配

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

1.2 默认自动装配

  1. 如果所有的bean都按照同一类型自动装配,可以再<beans>元素中加default-autowire属性。这个属性默认为none,表示不使用自动装配。可以设置为byName等类型。<bean>中的autowire会覆盖default-autowire属性。<property>会覆盖自动装配的值。
  2. autowire=“constructor”时,不能与<constructor-arg>同时存在。其他类型可以于<property>同时存在。
  1. 使用注解装配

    spring容器是默认禁用注解装配的。要启动,最简单的就是context命名空间的

    1.spring自带的@Autowired注解

    2.JSR-330的@Inject注解

    3.JSR-250的@Resource注解

2.1 @Autowired

  1. 有了这个注解,spring会按byType自动装配。这个注解可以加在setter方法上,还可以加在需要自动装配Bean的任意方法上,还可以加在构造器上。这个注解可以直接加在属性上,并删除setter方法。
  2. 这个注解必须只能有一个Bean匹配到注解的参数或属性中。没有匹配Bean或匹配多个Bean会有问题。

2.1.1可选的自动装配

  1. 默认情况下,这个注解标识的属性或参数必须是可装配的。没有Bean装配到,就会报NoSuchBeanDefinitionException。这个时候可以设置required=false来设置自动装配是可选的。没有匹配到Bean就会为null
  2. @Autowired(required=false)
  3. private A a;
  4. required可以用于@Autowired使用的任何地方,但是在构造器中,只能有一个构造器是requiredtrue,其他都要设置为false。当@Autowired标注多个构造器时,spring会从满足条件的构造器中选择入参最多的构造器。

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

  1. @Autowired
  2. @Qualifier("a")//指定a,默认从id找
  3. private A a;
  4. 相当于把byType转为了byName。缩小了自动装配Bean的范围。还可以在Bean中声明
  5. <bean class="A">
  6. <qualifier value="a"/>//可以限定这个Bean为a
  7. </bean>
  8. @Qualifier("a")//可以限定这个Bean为a
  9. class A implement B{}
  10. @Autowired是减少spring xml配置的一种方式。但是使用它的类会引入spring的特定依赖。

2.2 @Inject

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

2.2.1限定@Inject所标注的属性

  1. @Autowired@Qualifier@Inject@Named对应
  2. @Inject
  3. @Named("a")
  4. private A a;
  5. @Qualifier注解缩小Bean的选择范围(默认使用Beanid),@Named通过BeanId标识可选择的Bean

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

  1. @Value可以装配简单值。
  2. @Value("jack")//这里面是一个表达式
  3. private String name;
  4. @Value("#{abc.name}")
  5. 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

  1. <context:component-scan>除了完成<context:annotation-config>一样的工作外,还允许Spring自动检测Bean和定义Bean。
  2. <context:component-scan//替代了<context:annotation-config>
  3. base-package="包">//会扫描指定的包及其子包,并找出能够自动注册的spring Bean
  4. </context:component-scan>

3.1为自动检测标注Bean

  1. 默认情况下<context:component-scan>查找使用构造型注解所标注的类。
  2. 1.@Component:通用的构造型注解,表示该类为spring组件
  3. 2.@Controller:表示该类定义为spring mvc controller
  4. 3.@Repository:表示该类为数据仓库。
  5. 4.@Service:表示该类定义为服务
  6. 5.使用@Component标识的任意自定义注解

3.2过滤组件扫描

  1. <context:component-scan>下面还有子元素<context:include-filter><context:exclude-filter>。只是用<context:component-scan>的情况下,spring只会去找基于注解的组件。但是还要包含一个没有注解的接口的所有实现类要怎么办。就是用<context:include-filter>
  2. <context:component-scan
  3. base-package="包">
  4. <context:include-filter type="assignable" expression="xxx.abc"/>
  5. </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的配置

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

4.2 定义一个配置类

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

4.3 声明一个简单Bean

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

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

简单值注入:

  1. @Bean
  2. public A get(){
  3. return new B(12);
  4. }
  5. @Bean
  6. public A get(){
  7. B b = new B();
  8. b.setName("jack");
  9. return B;
  10. }

引用注入:

  1. @Bean
  2. public A get(){
  3. return new B();
  4. }
  5. @Bean
  6. public C set(){
  7. return new C(get());
  8. }

这里调用get()不会调用get()方法而是调用spring上下文中的Bean。

发表评论

表情:
评论列表 (有 0 条评论,348人围观)

还没有评论,来说两句吧...

相关阅读