zoukankan      html  css  js  c++  java
  • @Autowired与@Resource源码区别

    1、废话不多讲,直接干:

    定位到

    populateBean(beanName, mbd, instanceWrapper); 依赖注入的入口
    

    2、主要看:PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);

    for (BeanPostProcessor bp : getBeanPostProcessors()) {
    				if (bp instanceof InstantiationAwareBeanPostProcessor) {
    					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
    					//依赖注入过程,@Autowired的支持
    					PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
    					if (pvsToUse == null) {
    						if (filteredPds == null) {
    							filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
    						}
    
    						//老版本用这个完成依赖注入过程,@Autowired的支持
    						pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
    						if (pvsToUse == null) {
    							return;
    						}
    					}
    					pvs = pvsToUse;
    				}
    			}
    

    3、这个方法就是对postprocessor接口的运用,查看其实现类,这两个类就是处理类,一个处理Autowired,一个处理Resource

     4、先看Autowired的吧

    InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
    		try {
    			metadata.inject(bean, beanName, pvs);
    		}

     第一行是从收集好的注解信息中,拿到注解信息,其实就是需要依赖注入的信息,再看 下面的方法

    element.inject(target, beanName, pvs);
    

      

     我们只看属性的依赖注入,所以是选择第一个实现方法。

    5、跟踪到这一段代码

    try {
    		value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
    }
    

    6、再跟踪到这里

    if (result == null) {
    	result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
    }
    

     7、进去后里面有很多判断,@value的解析也在内,暂时不做分析,直接定位到这里

    Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
    	if (matchingBeans.isEmpty()) {
    		if (isRequired(descriptor)) {
    			raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
    		}
    		return null;
    	}
    

     意思是找到候选者bean,findAutowireCandidates()方法中是根据type来找到所有的beanName,也就是根据类型查找

    如果候选者是空,那么说明确实没有找到对应的依赖bean,注入值是空,如果注解上没有标注可以注入为空标记,则抛异常。

    8、下面就比较有意思了

    if (matchingBeans.size() > 1)
    

      如果根据type找到不止一个bean,此时要另做判断,直接在代码后面做注释吧。

    protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
    		Class<?> requiredType = descriptor.getDependencyType();
    		String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);寻找一个有@Primary注解的实现类作为依赖注入的类
    		if (primaryCandidate != null) {
    			return primaryCandidate;
    		}
    		String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);寻找一个有@Priority(2) 注解的实现类,并且取值最小的那一个。
    if (priorityCandidate != null) {
    return priorityCandidate;
    } // Fallback                                               在下面没看懂,不做解释
    for (Map.Entry<String, Object> entry : candidates.entrySet()) {
    String candidateName = entry.getKey();
    Object beanInstance = entry.getValue();
    if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance))
    || matchesBeanName(candidateName, descriptor.getDependencyName())) {
    return candidateName;
    }
    } return null;
    }

      如果以上都没判断出合格的bean则返回空。

    9、最后else中是只有一个候选bean

    else {
    				// We have exactly one match.
    				Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
    				autowiredBeanName = entry.getKey();
    				instanceCandidate = entry.getValue();
    			}
    

     10、最后调用getBean操作

    instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
    

      总结一下:根据类型查找候选者,如果候选者为空,则注入一个空;如果是多个,查找最合适的那一个,都不合适返回空;如果

    刚刚是一个,则调用getBean,返回bean。区别的话,等下一篇介绍@Resource后,自然而然就明白了。

     

      

  • 相关阅读:
    安装 oracle 11g 发行版 出现错误:由于以下错误,Enterprise Manager配置失败,启动Database Control时出错
    ORACLE_SID的查找
    visual studio 2017 编译v140 TRACKER : error TRK0005: Failed to locate: "CL.exe". 系统找不到指定的文件
    mysql 数据库表名大小写问题
    Windows下部署mongodb
    where case 使用
    虚拟机,云服务器搭建vulhub靶场
    [De1CTF 2019]SSRF Me
    [2020YCTF]web1-rce_nopar
    [2020YCTF]
  • 原文地址:https://www.cnblogs.com/zxg-blog/p/15067160.html
Copyright © 2011-2022 走看看