@Autowired與@Resource的區別


@Autowired@Resource相同點 

兩者都可以寫在字段和setter方法上。兩者如果都寫在字段上,那么就不需要再寫setter方法。

@Autowired@Resource不同點


1.@Autowired(org.springframework.beans.factory.annotation.Autowired)屬於Spring的注解,@Resource(javax.annotation.Resource)屬於J2EE的注解。
2.@Autowired是通過byType注入的;@Resource是通過byName注入的;

@Resource有2個重要的屬性分別是name和type,Spring將@Resource注解的name屬性解析為bean的名字,而type則解析為bean的類型。所以使用name屬性,則使用byName的自動注入策略,而使用byType屬性時則使用byType自動注入策略。如果沒用指定name或者type則默認通過byName自動注入策略。

:最好是將@Resource放在setter方法上,因為這樣更符合面向對象的思想,通過set、get去操作屬性,而不是直接去操作屬性。


@Resource裝配順序

①如果同時指定了name和type,則從Spring上下文中找到唯一匹配的bean進行裝配,找不到則拋出異常。

②如果指定了name,則從上下文中查找名稱(id)匹配的bean進行裝配,找不到則拋出異常。

③如果指定了type,則從上下文中找到類似匹配的唯一bean進行裝配,找不到或是找到多個,都會拋出異常。

④如果既沒有指定name,又沒有指定type,則自動按照byName方式進行裝配;如果沒有匹配,則回退為一個原始類型進行匹配,如果匹配則自動裝配。

@Resource的作用相當於@Autowired,只不過@Autowired按照byType自動注入。

 

代碼演示:

定義一個 接口  OrderMapper,二個實現類 OrderService01、OrderService02。一個 PayService 調用 orderMapper 接口中的方法。

orderMapper

 

package com.example.service;

/**
* @author mingtian
* @version V1.0
* @Description
* @date 2019/12/9 16:57
*/
public interface OrderMapper {
/**
* 新增訂單方法
*/
void add();
}

OrderServiceImpl01

 

package com.example.service.impl;

import com.example.service.OrderMapper;
import org.springframework.stereotype.Component;

/**
* @author mingtian
* @version V1.0
* @Description 訂單接口實現類
* @date 2019/12/9 16:55
*/
@Component
public class OrderServiceImpl01 implements OrderMapper {
public void add() {
System.out.println("OrderService01");
}
}

OrderServiceImpl02

package com.example.service.impl;

import com.example.service.OrderMapper;
import org.springframework.stereotype.Component;

/**
* @author mingtian
* @version V1.0
* @Description 訂單接口實現類
* @date 2019/12/9 16:55
*/
@Component
public class OrderServiceImpl02 implements OrderMapper {
public void add() {
System.out.println("OrderService02");
}
}

PayService 使用 @Auwowried

 

package com.example.service.impl;

import com.example.service.OrderMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
* @author mingtian
* @version V1.0
* @Description PayService
* @date 2019/12/9 16:54
*/
@Component
public class PayService {

@Autowired
private OrderMapper orderMapper;

public void add() {
orderMapper.add();
}
}

配置類

package com.example.config;

import com.example.entity.Order;
import com.example.entity.Win10;
import org.springframework.context.annotation.*;

/**
* @author mingtian
* @version V1.0
* @Description
* @ComponentScan("com.example.entity") //開啟掃包范圍
* @date 2019/12/9 11:17
*/
@Configuration
@ComponentScan("com.example")
public class MyConfig {

}


測試類

package com.example.test;

import com.example.config.MyConfig;
import com.example.entity.FactoryBeanEntity;
import com.example.service.impl.PayService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
* @author mingtian
* @version V1.0
* @Description 測試類
* @date 2019/12/9 11:00
*/
public class Test005 {

public static AnnotationConfigApplicationContext context;

public static void main(String[] args) {
context = new AnnotationConfigApplicationContext(MyConfig.class);
PayService payService = (PayService) context.getBean("payService");
       payService.add();
System.out.println("bean:" + payService);

}
}

現在啟動報錯,錯誤信息如下:

十二月 09, 2019 5:23:50 下午 org.springframework.context.support.AbstractApplicationContext refresh

警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'payService': Unsatisfied dependency expressed through field 'orderMapper'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.example.service.OrderMapper' available: expected single matching bean but found 2: orderServiceImpl01,orderServiceImpl02

Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'payService': Unsatisfied dependency expressed through field 'orderMapper'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.example.service.OrderMapper' available: expected single matching bean but found 2: orderServiceImpl01,orderServiceImpl02

at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:643)

at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:116)

at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1422)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)

at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)

at org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$31/221036634.getObject(Unknown Source)

at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)

at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)

at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)

at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:879)

at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878)

at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)

at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:89)

at com.example.test.Test005.main(Test005.java:19)

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.example.service.OrderMapper' available: expected single matching bean but found 2: orderServiceImpl01,orderServiceImpl02

at org.springframework.beans.factory.config.DependencyDescriptor.resolveNotUnique(DependencyDescriptor.java:220)

at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1265)

at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1207)

at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640)

 

... 15 more

由上面報錯的錯誤信息可知,通過 @Autowired 注解注入的 orderMapper 找到了二個實現類導致的錯誤。

解決辦法:

方法1 使用 @Autowired + @Qualifier(value="orderServiceImpl01")  顯示的指定一個實現類

package com.example.service.impl;

import com.example.service.OrderMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
* @author mingtian
* @version V1.0
* @Description PayService
* @date 2019/12/9 16:54
*/
@Component
public class PayService {

@Autowired
@Qualifier(value = "orderServiceImpl01")
private OrderMapper orderMapper;

public void add() {
orderMapper.add();
}
}

方法2  使用@Resource(name="orderServiceImpl01")

package com.example.service.impl;

import com.example.service.OrderMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
* @author mingtian
* @version V1.0
* @Description PayService
* @date 2019/12/9 16:54
*/
@Component
public class PayService {

@Resource(name = "orderServiceImpl01")
private OrderMapper orderMapper;

public void add() {
orderMapper.add();
}
}

由上面的二種解決方法可知:

 @Autowired + @Qualifier(value="orderServiceImpl01") 等同於 @Resource(name="orderServiceImpl01")

 

方法3 使用 @Primary 注解 指定默認加載的類,這樣的話 直接在PayService 中 直接使用 @Autowired  一個注解即可,默認啟動就會加載 OrderServiceImpl01 這個類

package com.example.service.impl;

import com.example.service.OrderMapper;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

/**
* @author mingtian
* @version V1.0
* @Description 訂單接口實現類
* @date 2019/12/9 16:55
*/
@Primary
@Component
public class OrderServiceImpl01 implements OrderMapper {
public void add() {
System.out.println("OrderService01");
}
}

 

@Primary 這個注解 在 SpringBoot 多數據源的時候經常使用 ,用來設置加載默認的數據源(優先級)。

 

注意:使用 @Component 注解的時候,記得開啟掃包的范圍(使用 @ComponentScan("com.example")指定掃包范圍),不然啟動會報錯的。

 

 

 OrderMapper,二個實現類 OrderService01、OrderService02、


免責聲明!

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



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