Spring的自动注入,也叫自动装配,就是对spring中的bean进行属性赋值,Spring默认情况下是不开启自动装配的,要开启自动装配,需要显式的进行配置,spring提供的自动装配功能有四种,分别是no,byName,byType,constructor,( autodetect 这种模式已过时)
在spring的AutowireCapableBeanFactory接口中定义了这四种模式
public interface AutowireCapableBeanFactory{
//无需自动装配
int AUTOWIRE_NO = 0;
//按名称自动装配bean属性
int AUTOWIRE_BY_NAME = 1;
//按类型自动装配bean属性
int AUTOWIRE_BY_TYPE = 2;
//按构造器自动装配
int AUTOWIRE_CONSTRUCTOR = 3;
//过时方法,Spring3.0之后不再支持
@Deprecated
int AUTOWIRE_AUTODETECT = 4;
}
<bean id="cat_c" class="com.spring.auto.autowire.Cat">bean>
<bean id="dog_d" class="com.spring.auto.autowire.Dog">bean>
<bean id="test" class="com.spring.auto.autowire.Person">
<property name="cat" ref="cat_c"/>
<property name="dog" ref="dog_d"/>
<property name="say" value="测试"/>
bean>
public class Cat {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
'}';
}
}
public class User {
private String name;
private Cat cat;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Cat getCat() {
return cat;
}
public void setCat(Cat cat) {
this.cat = cat;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", cat=" + cat +
'}';
}
}
<bean id="myCat" class="com.ming.bean.Cat">
<property name="name" value="kitty">property>
bean>
<bean id="user" class="com.ming.bean.User" autowire="byName">
<property name="name" value="James">property>
bean>
测试方法
@Test
public void testAutoWired() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
User user = applicationContext.getBean(User.class);
System.out.println(user.toString());
}
1:当没有autowire="byName"属性时,输出结果为:User{name=‘James’, cat=null},默认不进行注入
2:当指定autowire="byName"属性时,cat的ID为myCat,输出结果为同1,没有匹配到,不注入
3:当指定autowire="byType"属性时,结果为User{name=‘James’, cat=Cat{name=‘kitty’}},注入成功
4:当执行autowire="byType"属性时,并且放开注释部分,则抛异常NoUniqueBeanDefinitionException
bean
中 ,通过构造方法的参数类型进行匹配,<bean id="cat" class="com.ming.bean.Cat">
<property name="name" value="kitty1">property>
bean>
<bean id="user" class="com.ming.bean.User" autowire="constructor">
<constructor-arg index="0" value="James">constructor-arg>
bean>
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
/**
* Declares whether the annotated dependency is required.
* Defaults to {@code true}.
*/
boolean required() default true;
}
查看该源码,该注解可以使用在构造方法上,方法上,属性,参数上,注解上,只有一个required属性,可以指定自动注入是否是必须的
定义service和repository
@Repository
public class UserRepositoryImpl {
private int id ;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return "UserRepositoryImpl{" +
"id=" + id +
'}';
}
}
@Service
public class UserServiceImpl {
@Qualifier("userRepository1")//指定ID进行注入
@Autowired//先按byType匹配,如果存在多个,则按byName匹配
//@Resource(name="userRepository1")java规范的注解进行注入
private UserRepositoryImpl userRepositoryImpl;
@Override
public String toString() {
return "UserServiceImpl{" +
"userRepositoryImpl=" + userRepositoryImpl +
'}';
}
//@Autowired//先按byType匹配,如果存在多个,则按byName匹配
public UserRepositoryImpl getUserRepositoryImpl() {
return userRepositoryImpl;
}
//@Autowired//先按byType匹配,如果存在多个,则按byName匹配,
public UserServiceImpl(@Autowired UserRepositoryImpl userRepositoryImpl) {
//也可以使用在参数上
this.userRepositoryImpl = userRepositoryImpl;
}
}
定义配置类
@Configuration
@ComponentScan(value = {"com.ming.dao","com.ming.service"})
public class AutoWiredConfig {
@Primary
@Bean("userRepository1")
public UserRepositoryImpl userRepository(){
UserRepositoryImpl userRepository = new UserRepositoryImpl();
userRepository.setId(2);
return userRepository;
}
}
测试方法
@Test
public void testAutoWired() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AutoWiredConfig.class);
UserServiceImpl userService = applicationContext.getBean(UserServiceImpl.class);
//判断注入的bean是哪个
System.out.println(userService.getUserRepositoryImpl() == applicationContext.getBean("userRepositoryImpl"));
applicationContext.close();
}
@Autowired:无论是使用在属性上,set方法上,还是构造方法上,其原则都是一样的:先byType进行注入,如果该类型在IOC容器中,有且只有一个,则进行注入,如果该属性类型在容器中存在多个时,则会根据属性名称进行byName进行匹配
**@Qualifier:**指定ID进行注入,当容器中存在属性类型的bean有多个时,可以通过该注解指定ID进行注入
**@Primary:**主要的,当容器中同一个类型的bean存在多个时候,有该注解的会首先注入,如果即通过该注解指定了首要注入bean,有通过 @Qualifier指定了ID进行注入,则会以 @Qualifier为准
@Resource(JSR250),@Inject(JSR330),这两个注解是java规范的注解,在spring中也是支持对bean的注入的
**@Resource:**默认是按照属性名称进行装配的,可以通过name属性来指定bean的ID进行注入,但是不支持spring的注解 @Primary,也没有required=false属性
**@Inject:**需要导入javax.inject的包,和@Resource一样,也不支持spring的注解 @Primary,也没有required=false属性
如果自定义的一些组件,想要使用spring的一些组件,比如ApplicationContext,BeanFactory等,可以实现spring给提供的xxxAware接口,在对象创建时,可以使用接口方法进行注入,spring的每个xxxAware接口都有xxxAwareProcessor后置处理器实现类,
public class Color implements ApplicationContextAware, BeanNameAware, EmbeddedValueResolverAware {
private ApplicationContext applicationContext;
@Override
public void setBeanName(String name) {
System.out.println("当前bean的名字:"+name);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("spring传入的IOC:"+applicationContext);
this.applicationContext = applicationContext;
}
@Override//该方法可以通过$来获取环境变量的值,通过#计算SPel表达式的值
public void setEmbeddedValueResolver(StringValueResolver resolver) {
String s = resolver.resolveStringValue("当前系统${os.name},计算#{10+20}");
System.out.println(s);
}
public ApplicationContext getApplicationContext() {
return applicationContext;
}
}
配置类
@Configuration
@Import(Color.class)
public class AutoWiredConfig {
}
测试方法
@Test
public void testAutoWired() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AutoWiredConfig.class);
Color color = applicationContext.getBean(Color.class);
System.out.println("判断获取的applicationContext是否一样"+(applicationContext == color.getApplicationContext()));
applicationContext.close();
}
//输出结果
当前bean的名字:com.ming.bean.Color
当前系统Windows 10,计算30
spring传入的IOC:org.springframework.context.annotation.AnnotationConfigApplicationContext@5ccd43c2, started on Mon Mar 16 23:55:14 CST 2020
判断获取的applicationContext是否一样true