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系列:自动注入(autowire)详解,高手在于坚持!