【Spring注解驱动开发】使用@Autowired@Qualifier@Primary三大注解自动装配组件,你会了吗

@Autowired 注解,可以对类成员变量、方法和构造函数进行标注,完成自动装配的工作。@Autowired 注解可以放在类,接口以及方法上。在使用@Autowired之前,我们对一个bean配置属性时,是用如下xml文件的形式进行配置的。

@Autowired 注解的源码如下所示。

package org.springframework.beans.factory.annotation;

import java.lang.annotation.Documented;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface Autowired {

boolean required() default true;

}

@Autowired 注解说明:

(1)默认优先按照类型去容器中找对应的组件,找到就赋值;

(2)如果找到多个相同类型的组件,再将属性名称作为组件的id,到 IOC 容器中进行查找。

@Qualifier注解

@Autowired是根据类型进行自动装配的,如果需要按名称进行装配,则需要配合@Qualifier 注解使用。

@Qualifier注解源码如下所示。

package org.springframework.beans.factory.annotation;

import java.lang.annotation.Documented;

import java.lang.annotation.ElementType;

import java.lang.annotation.Inherited;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Inherited

@Documented

public @interface Qualifier {

String value() default “”;

}

@Primary注解

在Spring 中使用注解,常使用@Autowired, 默认是根据类型Type来自动注入的。但有些特殊情况,对同一个接口,可能会有几种不同的实现类,而默认只会采取其中一种实现的情况下, 就可以使用@Primary注解来标注优先使用哪一个实现类。

@Primary注解的源码如下所示。

package org.springframework.context.annotation;

import java.lang.annotation.Documented;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

@Target({ElementType.TYPE, ElementType.METHOD})

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface Primary {

}

自动装配


在进行项目实战之前,我们先来说说什么是Spring组件的自动装配。Spring组件的自动装配就是:Spring利用依赖注入,也就是我们通常所说的DI,完成对IOC容器中各个组件的依赖关系赋值。

项目实战


测试@Autowired注解

这里,我们以之前项目中创建的dao、service和controller为例进行说明。dao、service和controller的初始代码分别如下所示。

  • dao

package io.mykit.spring.plugins.register.dao;

import org.springframework.stereotype.Repository;

/**

  • @author binghe

  • @version 1.0.0

  • @description 测试的dao

*/

@Repository

public class PersonDao {

}

  • service

package io.mykit.spring.plugins.register.service;

import io.mykit.spring.plugins.register.dao.PersonDao;

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

import org.springframework.stereotype.Service;

/**

  • @author binghe

  • @version 1.0.0

  • @description 测试的Service

*/

@Service

public class PersonService {

@Autowired

private PersonDao personDao;

}

  • controller

package io.mykit.spring.plugins.register.controller;

import org.springframework.stereotype.Controller;

/**

  • @author binghe

  • @version 1.0.0

  • @description 测试的controller

*/

@Controller

public class PersonController {

@Autowired

private PersonService personService;

}

可以看到,我们在Service中使用@Autowired注解注入了Dao,在Controller中使用@Autowired注解注入了Service。为了方便测试,我们在PersonService类中生成一个toString()方法,如下所示。

package io.mykit.spring.plugins.register.service;

import io.mykit.spring.plugins.register.dao.PersonDao;

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

import org.springframework.stereotype.Service;

/**

  • @author binghe

  • @version 1.0.0

  • @description 测试的Service

*/

@Service

public class PersonService {

@Autowired

private PersonDao personDao;

@Override

public String toString() {

return personDao.toString();

}

}

这里,我们在PersonService类的toString()方法中直接调用personDao的toString()方法并返回。为了更好的演示效果,我们在项目的 io.mykit.spring.plugins.register.config 包下创建AutowiredConfig类,如下所示。

package io.mykit.spring.plugins.register.config;

import org.springframework.context.annotation.ComponentScan;

import org.springframework.context.annotation.Configuration;

/**

  • @author binghe

  • @version 1.0.0

  • @description 测试自动装配组件的Config配置类

*/

@Configuration

@ComponentScan(value = {

“io.mykit.spring.plugins.register.dao”,

“io.mykit.spring.plugins.register.service”,

“io.mykit.spring.plugins.register.controller”})

public class AutowiredConfig {

}

接下来,我们来测试一下上面的程序,我们在项目的src/test/java目录下的 io.mykit.spring.test 包下创建AutowiredTest类,如下所示。

package io.mykit.spring.test;

import io.mykit.spring.plugins.register.config.AutowiredConfig;

import io.mykit.spring.plugins.register.service.PersonService;

import org.junit.Test;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**

  • @author binghe

  • @version 1.0.0

  • @description 测试自动装配

*/

public class AutowiredTest {

@Test

public void testAutowired01(){

//创建IOC容器

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AutowiredConfig.class);

PersonService personService = context.getBean(PersonService.class);

System.out.println(personService);

context.close();

}

}

测试方法比较简单,这里,我就不做过多说明了。接下来,我们运行AutowiredTest类的testAutowired01()方法,得出的输出结果信息如下所示。

io.mykit.spring.plugins.register.dao.PersonDao@10e92f8f

可以看到,输出了PersonDao信息。

那么问题来了:我们在PersonService类中输出的PersonDao,和我们直接在Spring IOC容器中获取的PersonDao是不是同一个对象呢?

我们可以在AutowiredTest类的testAutowired01()方法中添加获取PersonDao对象的方法,并输出获取到的PersonDao对象,如下所示。

@Test

public void testAutowired01(){

//创建IOC容器

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AutowiredConfig.class);

PersonService personService = context.getBean(PersonService.class);

System.out.println(personService);

PersonDao personDao = context.getBean(PersonDao.class);

System.out.println(personDao);

context.close();

}

我们再次运行AutowiredTest类的testAutowired01()方法,输出的结果信息如下所示。

io.mykit.spring.plugins.register.dao.PersonDao@10e92f8f

io.mykit.spring.plugins.register.dao.PersonDao@10e92f8f

可以看到,我们在PersonService类中输出的PersonDao对象和直接从IOC容器中获取的PersonDao对象是同一个对象。

如果在Spring容器中存在对多个PersonDao对象该如何处理呢?

首先,为了更加直观的看到我们使用@Autowired注解装配的是哪个PersonDao对象,我们对PersonDao类进行改造,为其加上一个remark字段,为其赋一个默认值,如下所示。

package io.mykit.spring.plugins.register.dao;

import lombok.AllArgsConstructor;

import lombok.Data;

import lombok.NoArgsConstructor;

import org.springframework.stereotype.Repository;

/**

  • @author binghe

  • @version 1.0.0

  • @description 测试的dao

*/

@Data

@NoArgsConstructor

@AllArgsConstructor

@Repository

public class PersonDao {

private String remark = “1”;

}

接下来,我们就在AutowiredConfig类中注入一个PersonDao对象,并且显示指定PersonDao对象在IOC容器中的bean的名称为personDao2,并为PersonDao对象的remark字段赋值为2,如下所示。

@Bean(“personDao2”)

public PersonDao personDao(){

return new PersonDao(“2”);

}

目前,在我们的IOC容器中就会注入两个PersonDao对象。那此时,@Autowired注解装配的是哪个PersonDao对象呢?

接下来,我们运行AutowiredTest类的testAutowired01()方法,输出的结果信息如下所示。

PersonDao{remark=‘1’}

可以看到,结果信息输出了1,说明:@Autowired注解默认优先按照类型去容器中找对应的组件,找到就赋值;如果找到多个相同类型的组件,再将属性名称作为组件的id,到 IOC 容器中进行查找。

那我们如何让@Autowired装配personDao2呢? 这个问题问的好,其实很简单,我们将PersonService类中的personDao全部修改为personDao2,如下所示。

package io.mykit.spring.plugins.register.service;

import io.mykit.spring.plugins.register.dao.PersonDao;

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

import org.springframework.stereotype.Service;

/**

  • @author binghe

  • @version 1.0.0

  • @description 测试的Service

*/

@Service

public class PersonService {

@Autowired

private PersonDao personDao2;

@Override

public String toString() {

return personDao2.toString();

}

}

此时,我们再次运行AutowiredTest类的testAutowired01()方法,输出的结果信息如下所示。

技术学习总结

学习技术一定要制定一个明确的学习路线,这样才能高效的学习,不必要做无效功,既浪费时间又得不到什么效率,大家不妨按照我这份路线来学习。

最后面试分享

大家不妨直接在牛客和力扣上多刷题,同时,我也拿了一些面试题跟大家分享,也是从一些大佬那里获得的,大家不妨多刷刷题,为金九银十冲一波!

@description 测试的Service

*/

@Service

public class PersonService {

@Autowired

private PersonDao personDao2;

@Override

public String toString() {

return personDao2.toString();

}

}

此时,我们再次运行AutowiredTest类的testAutowired01()方法,输出的结果信息如下所示。

技术学习总结

学习技术一定要制定一个明确的学习路线,这样才能高效的学习,不必要做无效功,既浪费时间又得不到什么效率,大家不妨按照我这份路线来学习。

[外链图片转存中…(img-vZFKia3B-1720084252433)]

[外链图片转存中…(img-Wl9vfm9K-1720084252434)]

[外链图片转存中…(img-rR7j9Yfi-1720084252434)]

最后面试分享

大家不妨直接在牛客和力扣上多刷题,同时,我也拿了一些面试题跟大家分享,也是从一些大佬那里获得的,大家不妨多刷刷题,为金九银十冲一波!

[外链图片转存中…(img-cOhPDany-1720084252435)]

[外链图片转存中…(img-LJXGHZF0-1720084252436)]

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值