【Spring】@Autowired 和 @Resource 注解區別 & @Configuration 和 @Bean 的作用


 

報錯:

啟動項目,發現有一個報錯:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.data.redis.core.RedisTemplate<java.lang.String, java.lang.Object>' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

 

發現過程:

Service服務中,該Bean被這樣使用,

@Service public class AServiceImpl implements AService { @Autowired private RedisTemplate<String, Object> redisTemplate; }

 

應用1 和 應用2 都引用了 Service服務。

應用1可以啟動成功,應用2啟動就報如上錯誤。

為什么呢?

 

初步改動:

將上述的@Autowired 修改為@Resource  應用2啟動即成功了。

@Service public class AServiceImpl implements AService { @Resource private RedisTemplate<String, Object> redisTemplate; }

 

 

提出問題:

問題1:@Autowired 和 @Resource 注解有什么區別?


問題2:使用@Autowired 為什么可以啟動成功?

 

 

問題解答:

問題1:

  @Autowired  和  @Resource 注解有什么區別?

解答:

  

(1)@Resource和@Autowired注解都是用來實現依賴注入的。@Autowired只按照byType 注入;@Resource默認按byName自動注入,也提供按照byType 注入; (2)@Autowired按類型裝配依賴對象,默認情況下它要求依賴對象必須存在,如果允許null值,可以設置它required屬性為false。 【這一點很重要,即上面報錯的原因】 @Resource有兩個中重要的屬性:name和type。name屬性指定byName,如果沒有指定name屬性,當注解標注在字段上,即默認取字段的名稱作為bean名稱尋找依賴對象,當注解標注在屬性的setter方法上,即默認取屬性名作為bean名稱尋找依賴對象。需要注意的是,@Resource如果沒有指定name屬性,並且按照默認的名稱仍然找不到依賴對象時, @Resource注解會回退到按類型裝配。但一旦指定了name屬性,就只能按名稱裝配了。 (3)那如果既想使用@Autowired,又想通過byName注入,可以搭配結合@Qualifier注解一起使用。【不僅這種情況,例如多個ServiceBean類型時候,定義的一個serviceBean1 一個是ServiceBean2,同種Type時候,也可以結合@Qualifier完成byName的注入】 (4)@Resource裝配順序 1. 如果同時指定了name和type,則從Spring上下文中找到唯一匹配的bean進行裝配,找不到則拋出異常   2. 如果指定了name,則從上下文中查找名稱(id)匹配的bean進行裝配,找不到則拋出異常   3. 如果指定了type,則從上下文中找到類型匹配的唯一bean進行裝配,找不到或者找到多個,都會拋出異常   4. 如果既沒有指定name,又沒有指定type,則自動按照byName方式進行裝配;如果沒有匹配,則回退為一個原始類型進行匹配,如果匹配則自動裝配; 【這里注意,既沒有指定name,又沒有指定type,最終能匹配到則完成自動裝配,如果最終name和type都沒匹配到,就會出現使用@Resource注入一個Bean是null的情況】 【這種情況下,@Resource和@Autowired(required = false)  就是一樣的效果,也就是最開始的問題問什么使用 @Resource啟動就成功了的原因】

 

問題2:

  使用@Autowired 為什么可以啟動成功?

解答:

Service模塊使用的地方

@Service public class AServiceImpl implements AService { @Autowired private RedisTemplate<String, Object> redisTemplate; }

 

應用1引用了Service模塊,應用1使用@Autowired可以啟動的原因是因為,應用1中對該Bean做了注入操作

import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; /** * redis 配置類 */ @Configuration public class RedisConfiguration { @Bean public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>(); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); redisTemplate.setConnectionFactory(redisConnectionFactory); return redisTemplate; } }

 

這里就要說到 @Configuration  和 @Bean  的作用了

(1)@Configuration與@Bean結合使用。 (2)@Configuration可理解為用spring的時候xml里面的<beans>標簽,@Bean可理解為用spring的時候xml里面的<bean>標簽。 (3)Spring Boot不是spring的加強版,所以@Configuration和@Bean同樣可以用在普通的spring項目中,而不是Spring Boot特有的,只是在spring用的時候,注意加上掃包配置。 (4)Bean注解的作用之一就是能夠管理第三方jar包內的類到容器中。如上,我們將RedisTemplate通過使用@Bean的方式,把這個類交到Spring容器進行管理。 (5)在@Configuration中被@Bean標記的方法,會被Spring進行CGLIB代理,從而進行增強。 (6)原理參考:https://blog.csdn.net/sundacheng1989/article/details/92783515

 

 

 

總結:

所以,

之所以應用1使用@Autowired啟動沒問題,根本原因就是 應用1中對該Bean做了注入操作,已經將該Bean注入到Spring容器中進行管理,而@Autowired默認required=true,所以啟動沒問題。
應用2使用@Autowired啟動會報錯,因為沒有對該Bean做注入操作,也沒有設置@Autowired的required=false,所以啟動失敗了,而使用@Resource雖然啟動成功了,但如果真正使用到該Bean,也是NULL的,也是有問題的。


所以應用2也需要對該Bean做注入操作。

 

 

===================================================================================================

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM