使用@Autowired、@Qualifier、@Primary注解自动装配组件

1.@Autowired、@Qualifier、@Primary注解

1.1.@Autowired注解

@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. @Autowired注解默认是优先按照类型去容器中找对应的组件,若找到则就赋值,相当于是调用了如下这个方法:
    applicationContext.getBean(类名.class);
    
  2. 如果找到多个相同类型的组件,那么是将属性名称作为组件的id,到IOC容器中进行查找,这时就相当于是调用了如下这个方法:
    applicationContext.getBean("组件的id");
    

1.2.@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 "";

}

1.3.@Primary注解

在Spring中使用注解时,常常会使用到@Autowired这个注解,它默认是根据类型Type来自动注入的。但有些特殊情况,对同一个接口而言,可能会有几种不同的实现类,而在默认只会采取其中一种实现的情况下,就可以使用@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 {

}

2.自动装配

Spring组件的自动装配就是Spring利用依赖注入,也就是我们通常所说的DI,完成对IOC容器中各个组件的依赖关系赋值。

3.程序案例

3.1.测试@Autowired注解

3.1.1.测试1

创建BookDao、BookService、BookServiceImpl和BookController

  • BookDao
    package com.tianxia.springannotation.dao;
    
    import org.springframework.stereotype.Repository;
    
    /**
     * BookDao
     * @author liqb
     * @date 2023-04-21 16:37
     **/
    // 名字默认是类名首字母小写
    @Repository
    public class BookDao {
    }
    
  • BookService
    package com.tianxia.springannotation.service;
    
    /**
     * BookService
     * @author liqb
     * @date 2023-04-21 16:38
     **/
    public interface BookService {
    }
    
    
  • BookServiceImpl
    package com.tianxia.springannotation.service.impl;
    
    import com.tianxia.springannotation.dao.BookDao;
    import com.tianxia.springannotation.service.BookService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    /**
     * BookServiceImpl
     * @author liqb
     * @date 2023-04-21 16:38
     **/
    @Service
    public class BookServiceImpl implements BookService {
    
        @Autowired
        private BookDao bookDao;
    
        /**
         * 打印方法
         * @author liqb
         * @date 2023-05-06 13:09
         */
        public void print() {
            System.out.println(bookDao);
        }
        
        @Override
        public String toString() {
            return "BookService [bookDao=" + bookDao + "]";
        }
    }
    
  • BookController
    package com.tianxia.springannotation.controller;
    
    import com.tianxia.springannotation.service.BookService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    
    /**
     * BookController
     * @author liqb
     * @date 2023-04-21 16:39
     **/
    @Controller
    public class BookController {
        
        @Autowired
        private BookService bookService;
    }
    

为了更好的看到效果,在项目的config包下创建MainConfigOfAutowired配置类,如下所示:

package com.tianxia.springannotation.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * 配置类
 * @author liqb
 * @date 2023-05-06 13:11
 **/
@Configuration
@ComponentScan({"com.tianxia.springannotation.service", "com.tianxia.springannotation.dao", "com.tianxia.springannotation.controller"})
public class MainConfigOfAutowired {
}

运行测试方法,输出结果如下所示:

/**
 * 测试方法
 * @author liqb
 * @date 2023-05-06 13:14
 */
@Test
public void test01() {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAutowired.class);

    BookService bookService = applicationContext.getBean(BookService.class);
    System.out.println(bookService);
    
    BookDao bookDao = applicationContext.getBean(BookDao.class);
		System.out.println(bookDao);

    applicationContext.close();
}

在这里插入图片描述

BookService类中使用@Autowired注解注入的BookDao对象和直接从IOC容器中获取的BookDao对象是同一个对象

3.1.2.测试2

在Spring容器中存在对多个BookDao对象,那么这时又该如何处理

对BookDao类进行改造,为其加上一个lable字段,并为其赋一个默认值,如下所示。

package com.tianxia.springannotation.dao;

import org.springframework.stereotype.Repository;

/**
 * BookDao
 * @author liqb
 * @date 2023-04-21 16:37
 **/
// 名字默认是类名首字母小写
@Repository
public class BookDao {

    private String lable = "1";

    public String getLable() {
        return lable;
    }

    public void setLable(String lable) {
        this.lable = lable;
    }

    @Override
    public String toString() {
        return "BookDao [lable=" + lable + "]";
    }
}

在MainConfigOfAutowired配置类中注入一个BookDao对象,并且显示指定该对象在IOC容器中的bean的名称为bookDao2,并还为该对象的lable字段赋值为2

package com.tianxia.springannotation.config;

import com.tianxia.springannotation.dao.BookDao;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * 配置类
 * @author liqb
 * @date 2023-05-06 13:11
 **/
@Configuration
@ComponentScan({"com.tianxia.springannotation.service", "com.tianxia.springannotation.dao", "com.tianxia.springannotation.controller"})
public class MainConfigOfAutowired {

    /**
     * 注入bookDao对象
     * @author liqb
     * @date 2023-05-06 13:27
     * @return
     */
    @Bean("bookDao2")
    public BookDao bookDao() {
        BookDao bookDao = new BookDao();
        bookDao.setLable("2");
        return bookDao;
    }
}

运行测试方法,输出结果如下所示:

/**
 * 测试方法
 * @author liqb
 * @date 2023-05-06 13:14
 */
@Test
public void test01() {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAutowired.class);

    BookService bookService = applicationContext.getBean(BookService.class);
    System.out.println(bookService);

    applicationContext.close();
}

在这里插入图片描述

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

让@Autowired注解装配bookDao2

将BookService类中的bookDao属性的名称全部修改为bookDao2即可,如下所示:

package com.tianxia.springannotation.service.impl;

import com.tianxia.springannotation.dao.BookDao;
import com.tianxia.springannotation.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * BookServiceImpl
 * @author liqb
 * @date 2023-04-21 16:38
 **/
@Service
public class BookServiceImpl implements BookService {

    @Autowired
    private BookDao bookDao2;

    /**
     * 打印方法
     * @author liqb
     * @date 2023-05-06 13:09
     */
    public void print() {
        System.out.println(bookDao2);
    }
    
    @Override
    public String toString() {
        return "BookService [bookDao=" + bookDao2 + "]";
    }
}

运行测试方法,输出结果如下所示:

在这里插入图片描述

结论:@Autowired注解默认是优先按照类型去容器中找对应的组件,找到就赋值;如果找到多个相同类型的组件,那么再将属性的名称作为组件的id,到IOC容器中进行查找。

3.1.3.测试3

@Autowired注解属性required

required=false这个玩意的意思就是说找到就装配,找不到就拉到,就别装配了

require= true,未找到相应的bean对象,Spring就会抛出了异常

package com.tianxia.springannotation.service.impl;

import com.tianxia.springannotation.dao.BookDao;
import com.tianxia.springannotation.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * BookServiceImpl
 * @author liqb
 * @date 2023-04-21 16:38
 **/
@Service
public class BookServiceImpl implements BookService {

    @Autowired(required = false)
    private BookDao bookDao2;

    /**
     * 打印方法
     * @author liqb
     * @date 2023-05-06 13:09
     */
    public void print() {
        System.out.println(bookDao2);
    }

    @Override
    public String toString() {
        return "BookService [bookDao=" + bookDao2 + "]";
    }
}

3.2.测试@Qualifier注解

显示指定@Autowired注解装配哪个组件

package com.tianxia.springannotation.service.impl;

import com.tianxia.springannotation.dao.BookDao;
import com.tianxia.springannotation.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

/**
 * BookServiceImpl
 * @author liqb
 * @date 2023-04-21 16:38
 **/
@Service
public class BookServiceImpl implements BookService {

    @Autowired
    @Qualifier("bookDao")
    private BookDao bookDao2;

    /**
     * 打印方法
     * @author liqb
     * @date 2023-05-06 13:09
     */
    public void print() {
        System.out.println(bookDao2);
    }

    @Override
    public String toString() {
        return "BookService [bookDao=" + bookDao2 + "]";
    }
}

运行测试方法,输出结果如下所示:

在这里插入图片描述

此时尽管字段的名称为bookDao2,但是使用了@Qualifier注解显示指定了@Autowired注解装配bookDao对象,所以,最终的结果中输出了bookDao对象的信息。

3.3.测试@Primary注解

在Spring中,对同一个接口而言,可能会有几种不同的实现类,而默认只会采取其中一种实现的情况下,就可以使用@Primary注解来标注优先使用哪一个实现类。

在MainConfigOfAutowired配置类的bookDao()方法上添加上@Primary注解,如下所示:

package com.tianxia.springannotation.config;

import com.tianxia.springannotation.dao.BookDao;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

/**
 * 配置类
 * @author liqb
 * @date 2023-05-06 13:11
 **/
@Configuration
@ComponentScan({"com.tianxia.springannotation.service", "com.tianxia.springannotation.dao", "com.tianxia.springannotation.controller"})
public class MainConfigOfAutowired {

    /**
     * 注入bookDao对象
     * @author liqb
     * @date 2023-05-06 13:27
     * @return
     */
    @Primary
    @Bean("bookDao2")
    public BookDao bookDao() {
        BookDao bookDao = new BookDao();
        bookDao.setLable("2");
        return bookDao;
    }
}

注释掉BookService类中bookDao字段上的@Qualifier注解

package com.tianxia.springannotation.service.impl;

import com.tianxia.springannotation.dao.BookDao;
import com.tianxia.springannotation.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

/**
 * BookServiceImpl
 * @author liqb
 * @date 2023-04-21 16:38
 **/
@Service
public class BookServiceImpl implements BookService {

    // @Qualifier("bookDao")
    @Autowired(required = false)
    private BookDao bookDao2;

    /**
     * 打印方法
     * @author liqb
     * @date 2023-05-06 13:09
     */
    public void print() {
        System.out.println(bookDao2);
    }

    @Override
    public String toString() {
        return "BookService [bookDao=" + bookDao2 + "]";
    }
}

运行测试方法,输出结果如下所示:
在这里插入图片描述

此时lable的值为2,这说明装配了MainConfigOfAutowired配置类中注入的bookDao2

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值