首頁 > 軟體

Spring Bean註冊與注入實現方法詳解

2022-10-26 14:02:42

上接【Spring】spring核心思想——IOC和DI

上篇文章結尾簡單介紹了一下使用 XML 註冊 Bean,這篇文章接著介紹一下 XML 註冊 Bean 和使用註解註冊、注入 Bean

1. 邏輯上的 Bean 註冊

2. XML 註冊 Bean 到自建的庫中

上篇文章介紹了使用 XML 三種註冊的三種方式 (直接注入、構造方法注入、set 方法注入),在這裡繼續介紹一下使用工廠方法 和 範例化工廠註冊 Bean

2.1 工廠方法

工廠方法分為靜態工廠方法和範例工廠方法

使用工廠方法註冊就是呼叫靜態工廠方法註冊 Bean

範例化工廠註冊就是呼叫範例工廠方法註冊 Bean

2.2 使用工廠方法和範例化工廠註冊 Bean

首先還是使用 XML 自建庫,在 Main 方法中對庫進行操作(這裡對庫的操作主要是列印 Bean)

import org.springframework.context.support.FileSystemXmlApplicationContext;
public class Main {
    public static void main(String[] args) {
        FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("spring-config.xml");
        String[] names = context.getBeanDefinitionNames();
        for (String name : names) {
            Object bean = context.getBean(name);
            String canonicalName = bean.getClass().getCanonicalName();
            System.out.println(name + "     " + canonicalName);
        }
        int count = context.getBeanDefinitionCount();
        System.out.println("一共有 " + count + "個");
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--    通過工廠註冊,bean 的範例化由工廠方法完成-->
    <bean id="工廠註冊" class="com.hsq.ioc3.SomeClass" factory-method="createPerson"/>

<!--    通過已經註冊的 bean 的實體方法註冊,bean 的範例化由我們自己完成-->
    <bean id="工具bean" class="com.hsq.ioc3.SomeClass"/>
    <bean id="通過範例化工廠註冊" factory-bean="工具bean" factory-method="instantCreatePerson"/>
</beans>
public class SomeClass {
    // 靜態方法(可以直接通過類名呼叫)
    // 作用:返回一個物件
    // 這類方法被稱為工廠方法
    public static Person createPerson() {
        System.out.println("createPerson 被呼叫");
        return new Person();
    }
    public Person instantCreatePerson() {
        System.out.println("instantCreatePerson 被呼叫");
        return new Person();
    }
}
public class Person {
    public Person() {
        System.out.println("Person 被呼叫");
    }
}

通過列印可以清楚的看到兩種方法都成功註冊 Person 物件

3. XML 配合註解進行 Bean 註冊

自建 XML 庫中的組態檔有所改變

用到的註解 @Component,此註解後邊會講到

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
<!--    掃描這個包下的所有類,如果沒在這個包下,即使加了註解接不會被注入-->
    <context:component-scan base-package="com.hsq.ioc3"/>
</beans>
import org.springframework.stereotype.Component;
@Component
public class World {
    public World() {
        System.out.println("World 被呼叫");
    }
}

通過列印可以清楚看到,World 物件被成功註冊

4. 使用註解註冊 Bean

使用註解註冊簡而言之就是使用某個註解修飾類或方法,對其進行註冊

使用註解註冊 Bean 是註冊進 Spring 提供的庫,就不需要自建庫了

4.1 註解方式註冊的必要條件

  • 要被註解修飾類
  • 被註冊的 Bean 要在 XXXApplication 所在包下,否則註冊不會成功

4.2 用到的註解

這幾個註解在 IOC 場景下,沒有區別,都是將類註冊進 Spring 庫,但在其他場景一般這樣用

@Component:沒有特殊作用時,都可以用

@Controller:SpringMVC中把此註解特殊化了,要求控制器類必須用此註解修飾

@Service:修飾中間資料整合的類

@Repository:修飾資料獲取類

@Configuration:修飾設定類

4.3 @Component註解注入

import org.springframework.stereotype.Component;
@Component
public class World {
    public World() {
        System.out.println("World() 被呼叫");
    }
}
@SpringBootApplication
public class IocAApplication {
   public static void main(String[] args) {
      ConfigurableApplicationContext context = SpringApplication.run(IocAApplication.class, args);
      String[] names = context.getBeanDefinitionNames();
      System.out.println("bean 陳列如下:");
      for (String name : names) {
         Object bean = context.getBean(name);
         String canonicalName = bean.getClass().getCanonicalName();
         System.out.println(name + "   " + canonicalName);
      }
      int count = context.getBeanDefinitionCount();
      System.out.println("一共 " + count + "個");
   }
}

通過列印清楚看到,物件被註冊

4.4 使用 @Bean 註解註冊

使用 @Bean 修飾方法,@Configuration 修飾類

此方法註冊就相當於 XML 中的工廠方法註冊

@Configuration
public class AppConfig {
    // <bean id="hsq" factory-bean="appConfig" factory-method="hsq" />
    // 以工廠方法註冊
    @Bean
    public String hsq() {
        return "hsq";
    }
    @Bean       // 這裡的 World 由 Spring 注入
    // 因為 createHello 被 Spring 呼叫
    public Hello createHello(@Autowired World world) {
        System.out.println("createHello(), world = " + world);
        return new Hello(world);
    }
}

5. 通過註解注入 Bean

需要用到 World 類時

  • 先讓 Hello 類被註冊到 Spring 容器,並且範例化過程交給 Spring。———— @Component 修飾 Hello 類
  • 要求 World 類被註冊到 Spring 中(類註冊或者方法註冊都可以)
  • 使用構造方法、set 方法、屬性直接注入三種方法注入bean——使用 @Autowired 修飾
import org.springframework.stereotype.Component;
@Component
public class World {
    public World() {
        System.out.println("World() 被呼叫");
    }
}

構造方法注入

@Component
public class Hello {
    @Autowired      // 這個註解其實可以不寫,但是建議寫上,主要是讓看程式碼的人知道我們的 World 物件是被注入的
                    // 如果有多個構造方法,告訴 Spring,範例化物件是,應該呼叫哪個
    public Hello(World world) {
        System.out.println("Hello(), world = " + world);
    }
}

set 方法注入

@Component
public class Hello2 {
    @Autowired          // 這裡的此註解必須寫上
    public void setWorld(World world) {
        System.out.println("setWorld(), World = " + world);
    }
}

屬性直接注入

@Component
public class Hello3 {
    @Autowired
    public World world;     // world 屬性的值會被 Spring 容器物件注入
    public void printWorld() {
        System.out.println("printWorld(), world = " + this.world);
    }
}

6. 注入時的一個坑點

當使用以下方法注入時,會注入進 NULL 值,而非物件,原因已在下面程式碼的註釋中寫出

// 發生在 set 注入 / 屬性直接注入上
@Component
public class 注入時的一個坑點 {
    @Autowired
    public World world;
    public 注入時的一個坑點() {
        // 構造方法先執行,然後再進行注入(屬性注入 / set 注入)
        // 所以,構造方法執行的時候,注入還沒有發生,所以還是 null
        // 所以一般建議使用構造方法注入
        System.out.println("注入時的一個坑點(), world = " + this.world);
    }
}

7. 獲取 庫中的物件

ConfigurableApplicationContext context = SpringApplication.run(IocAApplication.class, args);
Object world1 = context.getBean("world");         // 根據 id 獲取 bean
World world2 = context.getBean(World.class);         // 根據型別獲取 bean
World world = context.getBean("world", World.class);      // 根據 id + 型別獲取 bean

到此這篇關於Spring Bean註冊與注入實現方法詳解的文章就介紹到這了,更多相關Spring Bean註冊與注入內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com