spring--自动装配

之前我们要注入依赖都是通过手动注入的,关于手动注入可以参考四种注入方式

而spring开发者意识到这种手动注入太麻烦了,于是就有了自动装配注入,不过仅针对bean的注入,不支持字符串等数据类型注入

spring实现自动装配的方式有两种,一种是通过xml文件,另一种是通过注解

手动注入的优先级比自动装配的优先级更高,如果两种都使用了,手动注入会覆盖自动装配-----原因是注解配置先于xml配置, 后者会覆盖前者

通过xml文件实现自动装配

Animal.java

package test_one;

public class Animal {
    private Dog dog;

    public Dog getDog() {
        return dog;
    }

    public void setDog(Dog dog) {
        this.dog = dog;
    }
    public void print() {
        System.out.println(dog);
    }
}
package test_one;
//Dog.java
public class Dog {
    
}

bean.xml

<!--自动配置-->
<bean id="dog" class="test_one.Dog" />
<bean id="animal" class="test_one.Animal" autowire="byName"/>

分析上面的代码

autowire=“byName" 表示属性名与id名相匹配,基于setter注入

具体是 通过setXxx得到属性名,然后与xml文件中的bean进行匹配,与bean的id名相同的匹配成功

所以使用byName方式需要确保属性名与依赖的id名相同

autowire的装配方式有:byName, byType, constructor, default, no

autowire="byType"  属性类型与class=""最后的类名匹配, 基于setter注入

autowire="constructor"  构造函数参数类型去匹配,基于构造函数注入

为什么说是通过构造函数参数类型匹配?  将参数名改成其他的依然成功

由于一个bean可能不止一个构造函数,所以到底选哪个构造函数呢? 相当于贪婪模式匹配,选尽可能多依赖并且全部依赖找到,参数数量倒叙的顺序逐一匹配,直到有一个构造函数中的全部参数都匹配到

autowire="default"  按default-autowire所选取的方式

根元素有default-autowire属性,这个属性可选值有(no|byName|byType|constructor|default)

如果bean选择default的方式自动装配,那么就是选择default-autowire属性的值

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.3.xsd"
       default-autowire="byName">
</beans>

通过注解实现自动装配

 @Autowired注解可以写在属性上也可以写在setter上, 还可以写在构造函数上; 所以它既基于setter,又基于构造函数

@Autowired优先通过属性类型去找到到依赖, 如果找到多个相同类型,再通过属性名称和id名去匹配

@Qualifier(value="id名")   指定需要装配的bean; 会直接使用@Qualifier注解进行匹配,如果id名不存在会报错

什么情况会使用到@Qualifier注解:当ioc容器根据属性类型去容器中找找到多个相同类型的组件,再将属性的名称作为组件(bean)的id去容器中查找找不到时就是用这两个注解搭配,指定需要装配的bean的id

Animal.java

package test_one;

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

public class Animal {
    @Autowired
    @Qualifier(value="dog")
    private Dog dog;
    private Cat cat;
 
  @Autowired   public Animal(Cat cat){
    this.cat=cat;
  }
public Dog getDog() { return dog; } public void setDog(Dog dog) { this.dog = dog; } @Autowired public void setCat(Cat cat) { this.cat=cat; } public void print() { System.out.println(dog+" \n"+cat); } }
package test_one;

public class Dog {
    
}
package test_one;

public class Cat {

}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:p="http://www.springframework.org/schema/p" 
        xmlns:c="http://www.springframework.org/schema/c"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
                http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
        <context:annotation-config/>

<bean id="dog" class="test_one.Dog" />
<bean id="cat" class="test_one.Cat" />
<bean id="animal" class="test_one.Animal" />
</beans>    

 

 @Resource注解  和@Autowired一样实现自动装配功能,不常用

属于JSR250规范

但是跟@Autowired不一样的是,它默认是按照组件名称进行装配的,按照组件名称找不到在根据属性类型去查找,再找不到就报错;

这个注解属于javaEE的规范, 在spring中是用不了的

 

 @Inject注解

属于JSR330规范, 需要拉去JSR330依赖和导入javax.inject.*;

@Inject是根据类型进行装配的

如果再加上@Named("id名") , 那么就会改为id名精准匹配, 如果该id名不存在,会报错

使用方法和@Autowired一样,可用于属性, setter, 构造函数

    @Inject
    @Named("cat")
    private Cat cat;

 

 @Primary

但匹配得到多个候选者bean时,会选择@Promary标识的bean (自动装配中未使用精准匹配 @Qualifier @Named等)

@Primary 是与@Bean搭配的

 

参考:spring--自动装配(非常详细)

Spring系列:自动注入(autowire)详解,高手在于坚持!

 

posted @ 2022-02-28 23:23  binbin_cloud  阅读(441)  评论(0编辑  收藏  举报