zoukankan      html  css  js  c++  java
  • CURD工程师——自动装配注解

    在CRUD的过程中,我们经常使用到一个注解@Autowired
    当然@Resource也会经常使用到
    三者的区别:
    @Resource注解方式进行装配,默认按名称装配,当找不到与名称匹配的bean才会按类型装配
    @Autowired自动装配具有兼容类型的单个bean属性。可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。
    @Autowied的使用来代替set方法。(property属性通过调用setter进行赋值)

    @Autowired其实就是自动装配,而在Spring中有三种方法可以进行装配

    1.在xml中显式配置

    //这种方法比较古老了,现在一般很少用到
    <bean id="chinese" class="lrf.spring.duty.ChineseImpl">
      <constructor-arg>
           <list>
                <value>李白</value>
                <value>杜甫</value>
                <value>苏轼</value>
           </list>
      </constructor-arg>

    2.在java中显式配置

    //创建配置类创建javaConfig类的关键在于为其添加 @Configuration注解,@Configuration注解表明这个类是一个配置类,该类应该包含Spring上下文中如何创建bean的细节。
    //之前我们都是依赖组件扫描来发现Spring应该创建的bean。尽管可以同时使用组件扫描和显示配置,但是现在我们去掉了 @CompnentScan注解,现在的CDPlayerConfig类就没有任何作用了。
    //如果现在运行之前的测试类,就会失败,并且出现BeanCreationException异常。
    @Configuration
    public class CDPlayerConfig {
     
    }
    
    //声明简单的bean
    //@Bean注解会告诉Spring这个方法会返回一个对象,该对象要注册为Spring应用上下文中的bean。
    @Bean
    public CompactDisc sgtPeppers() {
     return new SgtPeppers();
    }
    
    xml更加万能,适用于任何场合,维护更加方便
    注解 不是自己的类使用不了,维护相对复杂

    3.隐式的bean发现机制和自动装配

    从Spring2.5开始,开始支持使用注解来自动装配Bean的属性。它允许更细粒度的自动装配,我们可以选择性的标注某一个属性来对其应用自动装配。

    Spring支持几种不同的应用于自动装配的注解。

    • Spring自带的@Autowired注解。
    • JSR-330的@Inject注解。
    • JSR-250的@Resource注解。

    默认情况下,它具有强制契约特性,其所标注的属性必须是可装配的。如果没有Bean可以装配到Autowired所标注的属性或参数中,那么你会看到NoSuchBeanDefinitionException的异常信息。

    public Object doResolveDependency(DependencyDescriptor descriptor, String beanName,
      Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
      
     //查找Bean
     Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
     //如果拿到的Bean集合为空,且isRequired,就抛出异常。
     if (matchingBeans.isEmpty()) {
     if (descriptor.isRequired()) {
      raiseNoSuchBeanDefinitionException(type, "", descriptor);
     }
     return null;
     }
    }

    我记得曾经有个面试题是这样问的:Autowired是按照什么策略来自动装配的呢?
    关于这个问题,不能一概而论,你不能简单的说按照类型或者按照名称。但可以确定的一点的是,它默认是按照类型来自动装配的,即byType。

    默认按照类型装配

    关键点findAutowireCandidates这个方法。

    protected Map<String, Object> findAutowireCandidates(
     String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
      
     //获取给定类型的所有bean名称,里面实际循环所有的beanName,获取它的实例
     //再通过isTypeMatch方法来确定
     String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
      this, requiredType, true, descriptor.isEager());
       
     Map<String, Object> result = new LinkedHashMap<String, Object>(candidateNames.length);
      
     //根据返回的beanName,获取其实例返回
     for (String candidateName : candidateNames) {
     if (!isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, descriptor)) {
      result.put(candidateName, getBean(candidateName));
     }
     }
     return result;
    }

    如果查到类型的多个实例,Spring已经做了判断。

    public Object doResolveDependency(DependencyDescriptor descriptor, String beanName,
      Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
       
     //按照类型查找Bean实例
     Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
     //如果Bean集合为空,且isRequired成立就抛出异常
     if (matchingBeans.isEmpty()) {
     if (descriptor.isRequired()) {
      raiseNoSuchBeanDefinitionException(type, "", descriptor);
     }
     return null;
     }
     //如果查找的Bean实例大于1个
     if (matchingBeans.size() > 1) {
     //找到最合适的那个,如果没有合适的。。也抛出异常
     String primaryBeanName = determineAutowireCandidate(matchingBeans, descriptor);
     if (primaryBeanName == null) {
      throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet());
     }
     if (autowiredBeanNames != null) {
      autowiredBeanNames.add(primaryBeanName);
     }
     return matchingBeans.get(primaryBeanName);
     } 
    }

    最后我们回到问题上,得到的答案就是:@Autowired默认使用byType来装配属性,如果匹配到类型的多个实例,再通过byName来确定Bean。

  • 相关阅读:
    移动app测试浅析
    Instruments 使用指南
    手机APP测试的几大点
    Python之路【目录】
    Delphi TreeView – 自动展开树形结构
    Delphi TreeView – 自动给标题上加图片
    Delphi 发送邮件 通过Office Outlook
    Delphi Create(nil), Create(self), Create(Application)的区别
    Delphi StringReplace – 替换字符函数
    Delphi MessageBox
  • 原文地址:https://www.cnblogs.com/SmartCat994/p/13183770.html
Copyright © 2011-2022 走看看