day06-Spring管理Bean-IOC-04

一刀一個小西瓜發表於2023-01-19

Spring管理Bean-IOC-04

3.基於註解配置bean

3.1基本使用

3.1.1說明

基本說明:基於註解的方式配置bean,主要是專案開發中的元件,比如Controller,Service和Dao

元件的註解形式有:

  1. @Component 表示當前註解標識的是一個元件
  2. @Controller 表示當前註解標識的是一個控制器,通常用於Servlet
  3. @Service 表示當前註解標識的是一個處理業務邏輯的類,通常用於Service類
  4. @Repository 表示當前註解標識的是一個持久化層的類,通常用於Dao類

3.1.2快速入門

應用案例:使用註解的方式來配置Controller /Service/ Repository/ Component

程式碼實現:

1.使用註解方式,需要引入spring-aop.jar包,該jar包位於spring/lib下

2.建立 UserAction.java、UserService.java、UserDao.java、MyComponent.java

image-20230119165839094

UserDao:

package com.li.component;

import org.springframework.stereotype.Repository;

/**
 * @author 李
 * @version 1.0
 * 使用 @Repository 表示該類是一個Repository,一個持久化層的類/物件
 */
@Repository
public class UserDao {
}

UserService:

package com.li.component;

import org.springframework.stereotype.Service;

/**
 * @author 李
 * @version 1.0
 * @Service 標識該類是一個Service類/物件
 */
@Service
public class UserService {
}

UserAction:

package com.li.component;

import org.springframework.stereotype.Controller;

/**
 * @author 李
 * @version 1.0
 * @Controller 標識該類是一個控制器Controller,通常該類是一個Servlet
 */
@Controller
public class UserAction {
}

MyComponent:

package com.li.component;

import org.springframework.stereotype.Component;

/**
 * @author 李
 * @version 1.0
 * @Component 用於標識該類是一個元件,是一個通用的註解
 */

@Component
public class MyComponent {
}

上面我們在類中新增了註解,但是還沒有在配置檔案中指定容器要掃描哪個包下的註解類

3.配置beans04.xml:

<!--配置容器要掃描的包:
    1.component-scan 表示對指定的包下的類進行掃描,並建立物件到容器
    2.base-package 指定要掃描的包
    3.下面整個配置的含義是:當spring容器建立/初始化時,會掃描 com.li.component 包下
      的所有含有四種註解(Controller/Service/Repository/Component)的類,
      並將其例項化,生成物件,放入到ioc容器
-->
<context:component-scan base-package="com.li.component"/>

注意引入context名稱空間

4.測試

//透過註解來配置Bean
@Test
public void setBeanByAnnotation() {
    ApplicationContext ioc = new ClassPathXmlApplicationContext("beans04.xml");
    System.out.println("ok");
}

System.out.println("ok");旁打上斷點,點選debug。

檢視ioc物件-->beanFactory-->singletoObjects-->table的屬性。因為table屬性有很多null值,為了顯示方便,這裡配置了IDEA不顯示null值

image-20230119172330944

如下,spring容器中成功建立了四個物件,並且在預設情況下,按照註解方式進行掃描建立的物件,它對應的id就是它的類名(首字母小寫)

其他的物件是系統自帶的

image-20230119172804431

檢視型別id(key)

image-20230119172903347

因為配置的這四個物件是單例物件,因此可以直接透過類的型別來獲取:

因為spring在建立時賦予了預設id,也可以透過id來獲取

//透過註解來配置Bean
@Test
public void setBeanByAnnotation() {
    ApplicationContext ioc = new ClassPathXmlApplicationContext("beans04.xml");
    UserDao userDao = ioc.getBean(UserDao.class);
    UserService userService = ioc.getBean(UserService.class);
    UserAction userAction = ioc.getBean(UserAction.class);
    MyComponent myComponent = ioc.getBean(MyComponent.class);
    System.out.println("userDao=" + userDao);
    System.out.println("userService=" + userService);
    System.out.println("userAction=" + userAction);
    System.out.println("myComponent=" + myComponent);
    System.out.println("ok");
}
image-20230119173810459

3.1.3注意事項和細節

  1. 基於註解配置bean,需要匯入spring-aop.jar包

  2. 必須在Spring配置檔案中指定“自動掃描的包”,IOC容器才能夠檢測到當前專案中哪些類被標識了註解

    (1)在配置時注意匯入context名稱空間

    (2)指定掃描的包時,可以使用萬用字元,如:com.li.component.*表示掃描com.li.component包下的類, 包括com.li.component包下的子包(遞迴掃描)

  3. Spring的IOC容器不能檢測一個使用了@Controller註解的類到底是不是一個真正的控制器。註解的名稱只是用於程式設計師自己識別當前標識的是什麼元件。其他的註解@Service、@Reposity 也是一樣。

    也就是說,Spring的容器只要檢測到註解就會生成物件,但是這個註解的含義spring不會識別,只是給程式設計師方便區分的

    如果你只在spring容器上用,@Controller、@Service、@Reposity基本是等價的;如果你用在springmvc上面,它們是有區別的:徹底弄懂@Controller 、@Service、@Component

  4. 配置只掃描滿足要求的類:

    如下面的resource-pattern="User*.class",表示掃描指定包下以User開頭的類

    <context:component-scan base-package="com.li.component" 
                            resource-pattern="User*.class" />
    

    一般來說,想要掃描某個類只需要寫上註解,不想掃描的類就不會寫註解,因此上面這種寫法不常使用

  5. 配置排除掃描的類:

    如果我們希望排除某個包/子包下的某種型別的註解,可以透過exclude-filter來指定

    (1)context:exclude-filter 指定要排除哪些類

    (2)type 指定排除方式(annotation 表示透過註解來排除)

    (3)expression 指定要排除的註解的全路徑

    下面的配置表示,在掃描com.li.component包下註解的類時,排除以@Service註解的類

    <context:component-scan base-package="com.li.component" >
    <!-- 排除哪些類, 以 annotaion註解為例(透過註解來排除) -->
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
    </context>
    
  6. 自定義規則指定掃描哪些註解類:

    <!--如果我們希望透過自己的規則,來掃描包/子包下的某些註解類,可以透過include-filter
        1. use-default-filters="false": 表示不使用預設的過濾/掃描機制
        2. context:include-filter: 表示只是掃描指定的註解的類
        3. type="annotation" 表示按照註解方式來掃描
        4. expression="org.springframework.stereotype.Controller" 指定要掃描的註解的全類路徑
     -->
    <context:component-scan base-package="com.li.component" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
    
  7. 在預設情況下,註解標識的類建立物件後,在容器中它預設對應的id就是它的類名(首字母小寫)

  8. 也可以使用註解的value屬性指定 id 值,並且 value 可以省略:

    image-20230119185023801 image-20230119202735732

3.2手動開發-簡單的Spring基於註解配置的程式

3.2.1需求說明

自己寫一個簡單的Spring容器,透過讀取類的註解(@Component、@Controller、@Service、@Repository),將物件注入到IOC容器。即不使用Spring原生框架,我們自己使用IO+Annotation+反射+集合實現,加深對Spring註解方式開發的理解。

3.2.2思路分析

3.2.3程式碼實現

步驟一.搭建基本結構並獲取掃描包

1.ComponentScan註解

package com.li.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author 李
 * @version 1.0
 * 模仿spring原生註解,自定義一個註解
 * 1. @Target(ElementType.TYPE) 指定ComponentScan註解可以修飾TYPE元素
 * 2. @Retention(RetentionPolicy.RUNTIME) 指定ComponentScan註解 的保留範圍
 * 3. String value() default "";  表示 ComponentScan 可以傳入一個value值
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ComponentScan {
    String value() default "";
}

2.MySpringConfig配置類

package com.li.annotation;

/**
 * @author 李
 * @version 1.0
 * 這是一個配置類,作用類似我們原生spring的容器配置檔案beans.xml
 */
@ComponentScan(value = "com.li.component")
public class MySpringConfig {
}

未完。。。

相關文章