Spring注解详解之自动注入(@Autowired,@Qualifier,@Primary)

概述

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;
}

四种装配模式

  • no :该默认是spring的默认设置,表示自动装配是关闭的,可以在bean标签里通过propertity标签进行显式的设置
<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>
  • byName:通过bean的名称进行注入,在进行属性自动注入时,通过属性名称在容器中匹配id为该属性名称的bean进行注入,有则注入,没有则不进行注入
  • byType:通过bean的类型进行注入,如果属性的类型在IOC容器中存在且唯一,则进行注入,如果该类型存在多个bean,则NoUniqueBeanDefinitionException异常
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="cat" class="com.ming.bean.Cat">
        <property name="name" value="kitty1"></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

  • constructor:通过构造函数进行自动注入,和byType类似, 在启用了自动装配的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>

@Autowired,@Qualifier,@Primary

@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.
	 * <p>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,@Inject

@Resource(JSR250),@Inject(JSR330),这两个注解是java规范的注解,在spring中也是支持对bean的注入的

**@Resource:**默认是按照属性名称进行装配的,可以通过name属性来指定bean的ID进行注入,但是不支持spring的注解 @Primary,也没有required=false属性

**@Inject:**需要导入javax.inject的包,和@Resource一样,也不支持spring的注解 @Primary,也没有required=false属性

Spring底层组件

如果自定义的一些组件,想要使用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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Java中,依赖注入(Dependency Injection)是一种设计模式,它可以通过将对象的创建和依赖关系的管理委托给容器来简化对象之间的依赖关系。在依赖注入中,使用注解是一种很方便的方式来声明和注入依赖关系。 在Spring框架中,常用的依赖注入注解包括@Resource、@Autowired、@Qualifier等。它们之间的联系如下: 1. @Resource @Resource注解是Java EE 5中定义的注解,它可以用来注入一个bean,或者注入一个指定名称的bean。当没有指定名称时,默认使用属性名作为bean的名称。@Resource注解的作用相当于@Autowired和@Qualifier的组合。 2. @Autowired @Autowired注解Spring框架中定义的注解,它可以自动装配一个bean,也可以通过指定名称来注入一个特定的bean。如果存在多个同类型的bean,可以使用@Qualifier注解来指定要注入的bean的名称。@Autowired注解的作用相当于@Resource和@Qualifier的组合。 3. @Qualifier @Qualifier注解Spring框架中定义的注解,它可以与@Autowired或@Resource注解一起使用,用来指定要注入的bean的名称。当存在多个同类型的bean时,使用@Qualifier注解来指定要注入的bean的名称。 综上所述,@Resource、@Autowired和@Qualifier都是用来注入依赖关系的注解,它们之间的联系是相互补充的。@Resource注解提供了类似@Autowired和@Qualifier的功能,而@Autowired注解提供了类似@Resource和@Qualifier的功能。@Qualifier注解可以与@Autowired或@Resource注解一起使用,用来指定要注入的bean的名称。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值