iT邦幫忙

2022 iThome 鐵人賽

DAY 14
0
Software Development

這些年,我們早該學會的Spring Framework系列 第 14

Day14 - Dependency Injection (9) Annotation-based configuration

  • 分享至 

  • xImage
  •  

Review

Container的職責在於創建、配置與組裝bean,昨天我們學到了
如何使用SpEL來讓我們更方便設定Bean

  • literal
  • 引用其它物件屬性
  • 引用其它bean
  • 調用靜態方法
  • 調用非靜態方法

今日將討論如何使用註解的方式來將bean設置到container中

Annotation-based configuration

簡單的說就是透過Java Annotation的方式進行配置,例如@Controller,而前面討論的是XML Schema-based configuration,兩者的配置方式都各有優缺點,詳細可以看Spring doc的說明Are annotations better than XML for configuring Spring?

Stereotype Annotations

翻譯作刻板印象註解,在系統架構分層中可以讓我們清楚了解物件是在哪一層主要負責的功能,Spring並不會區分這些註解

  • @Controller:控制器,建議給控制器層的組件註解,例如servlet
  • @Service:業務邏輯,建議給業務邏輯層組件的註解
  • @Repository:數據庫層(持久化層,dao層)
  • @Component:不屬於以上幾層的組件所給予的註解,例如WebUtils

註解配置的步驟

  • 給組件加入上面註解中的一個
  • xml設定檔啟用掃描組件功能
  • 需import aop 的JAR檔,沒加則會拋出java.lang.NoClassDefFoundError: org/springframework/aop/TargetSource

測試

package com.swj.controller;
import org.springframework.stereotype.Controller;
@Controller
public class EmpServlet {
}
package com.swj.dao;
import org.springframework.stereotype.Repository;
@Repository
public class EmpDao {
}
package com.swj.service;
import org.springframework.stereotype.Service;
@Service
public class EmpService {
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    
    <!-- 啟動註解掃描,掃描com.swj package之下的類   -->
    <context:component-scan base-package="com.swj"></context:component-scan>
</beans>
@Test
public void testDay14(){
    ApplicationContext ioc = new ClassPathXmlApplicationContext("bean14.xml");
    System.out.println("容器啟動完成....");
    for(String name:ioc.getBeanDefinitionNames()){
        System.out.println(name);
    }
}

Result
https://ithelp.ithome.com.tw/upload/images/20220930/20128084p5e84e4KpQ.jpg

配置細節

  • 組件id,default為類名小寫駝峰,可透過括號中修改id名稱,例如@Service("HelloEmpService")
  • scope default為singleton,可以透過@Scope進行修改,例如@Scope(value="prototype")

測試

@Service("HelloEmpService")
@Scope(value = "prototype")
public class EmpService {
}
@Test
public void testDay14(){
    ApplicationContext ioc = new ClassPathXmlApplicationContext("bean14.xml");
    System.out.println("容器啟動完成....");
    EmpService s1 = ioc.getBean("HelloEmpService", EmpService.class);
    EmpService s2 = ioc.getBean("HelloEmpService", EmpService.class);
    System.out.println(s1 == s2);
}

Result
https://ithelp.ithome.com.tw/upload/images/20220930/20128084adZNseRCXY.jpg

Customize Scanning

可以客製化要掃描組件,可根據屬性type決定要如何執行過濾(annotation、assignable)

context:include-filter

需要禁用默認全掃的規則才會生效

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 啟動註解掃描,掃描com.swj package之下的類,use-default-filters=false禁用默認全掃的規則   -->
    <context:component-scan base-package="com.swj" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
</beans>
@Test
public void testDay14(){
    ApplicationContext ioc = new ClassPathXmlApplicationContext("bean14.xml");
    System.out.println("容器啟動完成....");
    for(String name :ioc.getBeanDefinitionNames()){
        System.out.println(name);
    }
}

Result
https://ithelp.ithome.com.tw/upload/images/20220930/20128084e5zM6RixGl.jpg

context:exclude-filter

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 啟動註解掃描,掃描com.swj package之下的類  -->
    <context:component-scan base-package="com.swj">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
</beans>

Result
https://ithelp.ithome.com.tw/upload/images/20220930/20128084cZ58CRQGuQ.jpg

Reference


上一篇
Day13 - Dependency Injection (8) SpEL
下一篇
Day15 - Dependency Injection (10) @Autowired
系列文
這些年,我們早該學會的Spring Framework30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言