1. 程式人生 > 實用技巧 >2.2、基於註解的DI注入

2.2、基於註解的DI注入

學習資源:動力節點的2020最新Spring框架教程【IDEA版】-Spring框架從入門到精通

目錄


基於註解的 DI,是指通過 Spring 提供的註解完成容器物件的建立、屬性初始化,而不再需要使用配置檔案宣告建立 bean 了。

註解使用步驟:

  1. 匯入 maven 依賴 spring-context
  2. 在實體類加入註解
  3. 在 spring 配置檔案中,配置元件掃描器,用於指定掃描哪些包下的註解

Spring 常用註解:

  • @Component
  • @Respotory
  • @Service
  • @Controller
  • @scope
  • @Value
  • @Autowire
  • @Resource

0、準備工作

0.1、匯入 maven 依賴

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.5.RELEASE</version>
</dependency>

0.2、建立實體類


0.3、配置元件掃描器

元件掃描器的工作方式:spring 會掃描逼歷 base-package 指定的包及子包中所有的類,找到類中的註解,按照註解的功能建立物件或給屬性賦值。

配置元件掃描器,在配置檔案中加入:

<context:component-scan base-package="com.chen.pojo"/>

指定掃描多個包的方式:

  1. 使用多次元件掃描器,掃描不同的包
<context:component-scan base-package="com.chen.pojo"/>
<context:component-scan base-package="com.chen.domain"/>
......
  1. 使用分隔符 ; 或 , 分割多個包
<context:component-scan base-package="com.chen.pojo;com.chen.domain;......"/>
  1. 指定父包
<context:component-scan base-package="com.chen"/>

1、@Component

作用等同於配置檔案中的 <bean> ,用於向容器中建立物件。需要在實體類上使用註解 @Component ,該註解的 value 屬性用於指定該 bean 的 id 值,id 自定義唯一,value 屬性可預設。

使用例項:

  1. @Component(value="自定義名稱")
@Component(value="student")
public class Student{
    
}
  1. @Component("自定義名稱"),推薦使用
@Component(value="student")
public class Student{
    
}
  1. @Component(),此時 bean 會使用 spring 提供的預設名稱:類名首字母小寫
@Component()
public class Student{
    
}

另外, Spring 還提供了 3 個建立物件的註解:

  • @Repository:用於對持久層類(DAO 實現類)進行註解
  • @Service:用於對業務層類(Service 實現類)進行註解
  • @Controller:用於對控制器類(Controller 實現類)進行註解

這三個註解與 @Component 都可以建立物件,但這三個註解還有其他的含義:@Repository 建立持久層物件,持久層物件是可以操作資料庫的;@Service 建立業務層物件,業務層物件可以加入事務功能;@Controller 註解建立的物件可以作為處理器接收使用者的請求。

@Repository、@Service、@Controller 是用於給專案的物件分層的:持久層、業務層、控制層。而當你不確定某一個物件的角色時,可以使用 @Component 。


2、@Value

功能等同於 <\property name="" value=""> ,用於給簡單型別的屬性賦值。

需要在屬性上使用註解@Value,該註解的 value 屬性用於指定要注入的值。使用該註解完成屬性注入時,類中無需 setter。當然,若屬性有 setter,則也可將其加到 setter 上。

使用例項:

  1. 在屬性定義的上面使用,無需 setter ,推薦使用
@Componnet("student")
public class Student{
    
    // @Value(value = "張san"),value屬性可不寫
    @Value("張san")
    private String name;
    @Value("29")
    private int age;
}
  1. 在 setter 上使用
@Componnet("student")
public class Student{
    
    private String name;
    private int age;
    
    @Value("張三")
    public void setName(String name) {
        this.name = name;
    }
	@Value("29")
    public void setAge(String age) {
        this.age = age;
    }
}

3、@Scope

功能同 <\bean> 的scop 屬性相同,在實體類上使用,用於設定 bean 的作用域。

  • @Scope("singleton"):單例
  • @Scope("prototype"):多例

4、@Atuowired(不推薦使用了)

功能與 <bean ... autowire=""> 相同,用於為引用型別的屬性賦值。@Atuowired 預設使用的是 byType 自動從容器中裝配 Bean。

4.1、byType

byType 是 @Atuowired 的預設方式,直接在屬性上使用,類中無需 setter。若屬性有 setter,也可將其加到 setter 上。推薦直接在屬性上使用。

使用例項:

@Component("student")
public class Student {
    
    @Value("16")
    private int age;
    @Autowired
    private School school;
}

///////////////////////////////////////////////////////////////////////

@Component("school")
public class School {
    
    @Value("3000")
    private int area;
}

4.2、byName

需要再借助另一個註解 @Qualifier("容器中 bean 的 id"),才可以更改 @Atuowired 的自動裝配方式。

@Autowirted
@Qualifier(value="容器中bean的id")

使用例項:

@Component("student")
public class Student {
    
    @Value("16")
    private int age;
    
    @Autowired
    @Qualifier("stuSchool")
    private School school;
}

///////////////////////////////////////////////////////////////////////

@Component("stuSchool")
public class School {
    
    @Value("3000")
    private int area;
}

3.3、required

required 是 @Autowired 的一個屬性,預設值為 true。建議使用 true

  • true 表示如果引用型別賦值失敗,程式報錯終止執行
  • false 表示如果引用型別賦值失敗,程式正常執行,引用型別賦為 null、
@Component("student")
public class Student {
    
    @Value("16")
    private int age;
    
    @Autowired(required=true)
    private School school;
}

4、@Resource

@Resource 是 JDK 的註解,Spring 提供了對它的支援。

同 @Atuowired 一樣,@Resource 也是既可以 byType,也可以 byName,預設是 byName。

@Resource 可用在屬性上,也可以用在 setter 上,推薦直接用在屬性上。


4.1、byType

@Resource 註解若不帶任何引數, 採用預設 byName 的方式注入,若 byName 失敗,則轉而使用 byType。

使用例項:

@Component("student")
public class Student {
    
    @Value("16")
    private int age;
    
    @Resource
    private School school;
}

///////////////////////////////////////////////////////////////////////

@Component("stuSchool")
public class School {
    
    @Value("3000")
    private int area;
}

4.2、byName

@Resource 註解指定其 name 屬性的值,則 name 的值即為按照名稱進行匹配的 Bean 的 id。

@Component("student")
public class Student {
    
    @Value("16")
    private int age;
    
    @Resource(name="stuSchool")
    private School school;
}

///////////////////////////////////////////////////////////////////////

@Component("stuSchool")
public class School {
    
    @Value("3000")
    private int area;
}

5、註解與XML對比

註解的優點:

  • 方便
  • 直觀
  • 高效(程式碼少,沒有配置檔案的書寫那麼複雜)、

註解的缺點:

  • 以硬編碼的方式寫入到 Java 程式碼中,修改是需要重新編譯程式碼的

XML 方式優點是:

  • 配置和程式碼是分離的
  • 在 xml 中做修改,無需編譯程式碼,只需重啟伺服器即可將新的配置載入

缺點:

  • 編寫麻煩,效率低,大型專案過於複雜

最佳實踐:註解為主,配置檔案為輔