乐趣区

spring注解驱动开发8-自动装配-Autowired-Resource-Qualifier-Primary

@Autowired

spring 的注解, 用来做主动拆卸; 如果用于属性上:

首先依照 类型 匹配, 类型匹配失败会用 name 匹配;

如果匹配到 多个 : 再用@Qualifier("beanName") 的 beanName 来筛选, 看拆卸哪个 bean;

如果一个都匹配不到, 而且申明了属性 required=false , 不调用不会报错; 调用就会 NoSuchBeanDefinitionException;

不仅能够用在 属性 上, 也能够用到 办法 / 结构器 / 办法参数 上: (用在办法上和用在入参上意义是雷同的)

如果应用在 set 办法上和构造方法上, 都有入参; 不管有没有 @Autowired 注解在办法上和参数上, 都会从 IOC 容器中去拆卸, 不会报错;

@Qualifier

@Qualifier 的作用如上; 用来在拆卸某个类型的 bean 时, 找到多个 bean 后用它的 value 作为 name 来辨别;

@Primary

如果某个类型的 bean 在 IOC 容器中有多个能够匹配到; 在拆卸时又没有指定 @Qualifier(value=”beanName”); 此时, 就会首先筛选申明时标注了 @Primary 的 bean 来拆卸!

@Resource

JSR250 的注解, 属于 java 标准;

@Resource 默认先依照 name 来匹配, 如果 name 匹配不到, 再依照 类型 去匹配; 也能够和 @Qualifier 和 @Primary 一起应用;

@Resource 和 @Autowired 比拟:

不同点

  1. @Resource 首先依照 name 匹配, 匹配不到采纳 类型 ; @Autowired 首先依照 类型 匹配, 匹配到多个才会用 name 筛选;
  2. @Resource 是 JSR250 的注解, 是 java 标准定义的; @Autowired 是 spring 定义的注解;
  3. @Resource 没有 @Autowired(required=false)里的 required属性, 没有可选 bean, 即便不调用, 也会报: NoSuchBeanDefinitionException;
  4. @Resource 不能应用到 参数 构造方法 上; @Autowired 能够(ElementType.PARAMETER, ElementType.CONSTRUCTOR)!

共同点:

  1. 都有备选机制: 即 name类型 双备选, 一个找不到, 用另一个;
  2. 当匹配到多个时, 都能够配合应用 @Qualifier 和 @Primary 来辨别;
  3. 当匹配到多个时, 匹配到多个, 也没有 @Qualifier 和 @Primary 注解辨别, 两个注解都会报异样:
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.niewj.service.ProductService' available: expected single matching bean but found 2: productService,productService2

配置类: 这里有一个 ProductService 初始化: productService2

package com.niewj.config;

import com.niewj.service.ProductService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan({"com.niewj.controller", "com.niewj.service"})
public class AutowiredTestConfig {

    // @Primary
    @Bean(name = "productService2")
    public ProductService product2(){ProductService productService = new ProductService();
        productService.setLabel("2");
        return productService;
    }
}

Service 类: 这里也有一个 ProductService 注入 springIOC: productService(默认名字类名首字母小写)

package com.niewj.service;

import lombok.Data;
import org.springframework.stereotype.Service;

@Data
@Service
public class ProductService {
    private String label="1";
    public void print(){System.out.println("ProductService --> print");
    }
}

Controller 类:

package com.niewj.controller;

import com.niewj.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;

import javax.annotation.Resource;

@Controller
public class ProductController {//    // 不指定 @Qualifier("productService2") 时, 在 productService2 处应用 @Primary 也能首选 productService2
//    // 指定 @Qualifier("productService2")
//    @Qualifier("productService3")  // 如果没有指定 required=false, 匹配不到则会报告异样: NoSuchBeanDefinitionException
//    //  @Autowired(required = false)
//    @Autowired
//    private ProductService productService;

    @Autowired
    private ProductService productService2;

    public void doPrint(){System.out.println(productService2);
    }
}

测试用例:

package com.niewj;

import com.niewj.config.AutowiredTestConfig;
import com.niewj.controller.ProductController;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.util.stream.Stream;

/**
 * spring 主动拆卸
 */
public class AutowiredTest {

    @Test
    public void testAutowired() {AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AutowiredTestConfig.class);

        // 打印 spring 容器中的 BeanDefinition
        Stream.of(ctx.getBeanDefinitionNames()).forEach(e-> System.out.println(e));
        System.out.println("=============================");

        ProductController productController = ctx.getBean(ProductController.class);
        productController.doPrint();

        ctx.close();}

}

output:

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
autowiredTestConfig
bookController
productController
testController
subPacController
bookService
productService
productService2
=============================
ProductService(label=2)

主动拆卸原理:

@Autowired/@Value/@Inject 等注解都是用 AutowiredAnnotationBeanPostProcessor 类实现的~BeanPostProcessor;

同样的实现还有: Aware 接口

@ApplicationContextAware 能够获取 IOC 容器上下文;

@ApplicationEventPublisherAware 获取事件公布器;

@EnvironmentAware 获取属性配置信息;

@EmbeddedValueResolverAware 内置字段的解析, 能够反对 ${}表达式, spEL #{}等;

退出移动版