1. 程式人生 > >41. Spring Boot 使用Java程式碼建立Bean並註冊到Spring中【從零開始學Spring Boot】

41. Spring Boot 使用Java程式碼建立Bean並註冊到Spring中【從零開始學Spring Boot】

【視訊&交流平臺】

http://study.163.com/course/introduction.htm?courseId=1004329008&utm_campaign=commission&utm_source=400000000155061&utm_medium=share

http://study.163.com/course/introduction.htm?courseId=1004638001&utm_campaign=commission&utm_source=400000000155061&utm_medium=share

https://gitee.com/happyangellxq520/spring-boot

http://412887952-qq-com.iteye.com/blog/2321532


  

已經好久沒有講一些基礎的知識了,這一小節來點簡單的,這也是為下節的在Spring多數Boot中使用多資料來源做準備。

從Spring 3.0開始,增加了一種新的途徑來配置Bean Definition,這就是通過Java Code配置Bean Definition。

與XML和Annotation兩種配置方式不同點在於:

前兩種方式XML和Annotation的配置方式為預定義方式,即開發人員通過XML檔案或者Annotation預定義配置Bean的各種屬性後,啟動Spring容器,Spring容器會首先解析這些配置屬性,生成對應的Bean Definition,裝入到DefaultListtableBeanFactory物件的屬性容器中,以此同時,Spring框架也會定義內部使用的Bean定義,如Bean名為:org.springframework.context.annotation.internalConfigurationAnnotationProcessor”的 ConfigurationClassPostProcessor 定義。而後此刻不會做任何Bean Definition的解析動作,Spring框架會根據前兩種配置,過濾出BeanDefinitionRegistryPostProcessor 型別的Bean定義,並通過Spring框架生成對應的Bean物件(如 ConfigurationClassPostProcessor 例項)。。結合Spring 上下文原始碼可知這個物件是一個 processor 型別工具類,Spring 容器會在例項化開發人員所定義的 Bean 前先呼叫該 processor 的 postProcessBeanDefinitionRegistry(…) 方法。此處實現基於 Java Code 配置Bean Definition的處理。

基於 Java Code 解析 Bean 的順序圖

基於 Java Code的配置方式,其執行原理不同於前兩種。它是在 Spring 框架已經解析了基於 XML 和 Annotation 配置後,通過加入BeanDefinitionRegistryPostProcessor 型別的 processor 來處理配置資訊,讓開發人員通過 Java 程式設計方式定義一個 Java 物件。其優點在於可以將配置資訊集中在一定數量的 Java 物件中,同時通過 Java 程式設計方式,比基於 Annotation 方式具有更高的靈活性。並且該配置方式給開發人員提供了一種非常好的範例來增加使用者自定義的解析工具類。其主要缺點在於與 Java 程式碼結合緊密,配置資訊的改變需要重新編譯 Java 程式碼,另外這是一種新引入的解析方式,需要一定的學習成本。

提及一點的就是,Spring框架有3個主要的Hook類,分別是:

org.springframework.context.ApplicationContextAware 
它的setApplicationContext 方法將在Spring啟動之前第一個被呼叫。我們用來同時啟動Jdon框架。

org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor 
它的postProcessBeanDefinitionRegistry 和 postProcessBeanFactory 方法是第二和第三被呼叫,它們在Bean初始化建立之前啟動,如果Spring的bean需要的其他第三方中的元件,我們在這裡將其注入給Spring。

org.springframework.context.ApplicationListener 
用於在初始化完成後做一些事情,當Spring所有XML或元註解的Bean都啟動被建立成功了,這時會呼叫它的唯一方法onApplicationEvent。

下面我們來完成一個,自己通過java程式碼建立bean,並註冊為Spring管理。 

本例中,我們建立一個介面,然後建立該介面的2個實現類,分別命名不同的名字,然後在需要注入的地方使用@Qualifier 指定注入對應的例項。

介面com.kfit.demo.Shanhy.java

package com.kfit.demo;

publicinterface Shanhy {

     publicvoid dispaly();

}

實現類com.kfit.demo.ShanhyA.java

package com.kfit.demo;

publicclassShanhyA implements Shanhy{

     @Override

     publicvoid dispaly() {

         System.out.println("ShanhyA.dispaly()");

     }

}

實現類com.kfit.ShanhyB.java

package com.kfit.demo;

publicclass ShanhyBimplements Shanhy {

     @Override

     publicvoid dispaly() {

         System.out.println("ShanhyB.dispaly()");

     }

}

定義介面BeanDefinitionRegistryPostProcessor的實現:

com.kfit.config.

package com.kfit.config;

importorg.springframework.beans.BeansException;

importorg.springframework.beans.MutablePropertyValues;

importorg.springframework.beans.factory.annotation.AnnotatedBeanDefinition;

importorg.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition;

importorg.springframework.beans.factory.config.BeanDefinition;

importorg.springframework.beans.factory.config.BeanDefinitionHolder;

importorg.springframework.beans.factory.config.ConfigurableListableBeanFactory;

import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;

importorg.springframework.beans.factory.support.BeanDefinitionRegistry;

importorg.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;

import org.springframework.beans.factory.support.BeanNameGenerator;

importorg.springframework.context.annotation.AnnotationBeanNameGenerator;

importorg.springframework.context.annotation.Configuration;

import com.kfit.demo.ShanhyA;

import com.kfit.demo.ShanhyB;

/**

 *實現自己例項化bean並註冊為Spring管理

 *@author Angel(QQ:412887952)

 *@version v.0.1

 */

@Configuration

publicclassMyBeanDefinitionRegistryPostProcessorimplementsBeanDefinitionRegistryPostProcessor {

       //bean 的名稱生成器.

        private BeanNameGeneratorbeanNameGenerator =newAnnotationBeanNameGenerator();

       @Override

       publicvoidpostProcessBeanFactory(ConfigurableListableBeanFactorybeanFactory)throws BeansException {

              System.out.println("MyBeanDefinitionRegistryPostProcessor.postProcessBeanFactory()");

       }

       /**

        *先執行:postProcessBeanDefinitionRegistry()方法,

        *在執行:postProcessBeanFactory()方法。

        *

        */

       @Override

       publicvoidpostProcessBeanDefinitionRegistry(BeanDefinitionRegistryregistry)throws BeansException{

              System.out.println("MyBeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry()");

              /*

               *在這裡可以注入bean.

               */

              registerBean(registry,"shanyA", ShanhyA.class);

              registerBean(registry,"shanyB", ShanhyB.class);

       }

       /**

        *提供公共的註冊方法。

        *@param beanDefinitionRegistry

        *@param name

        *@param beanClass

        */

       privatevoidregisterBean(BeanDefinitionRegistryregistry,Stringname,Class<?>beanClass){

              AnnotatedBeanDefinitionannotatedBeanDefinition  =new AnnotatedGenericBeanDefinition(beanClass);

                //可以自動生成name

              StringbeanName = (name !=null?name:this.beanNameGenerator.generateBeanName(annotatedBeanDefinition,registry));

              //bean註冊的holer類.

              BeanDefinitionHolderbeanDefinitionHolder =newBeanDefinitionHolder(annotatedBeanDefinition,beanName);

              //使用bean註冊工具類進行註冊.

              BeanDefinitionReaderUtils.registerBeanDefinition(beanDefinitionHolder,registry);

       }

}

這個類裡的程式碼比較多,在這裡簡單的介紹下:方法postProcessBeanDefinitionRegistry()是用來註冊bean的;而具體註冊的程式碼比較是通用的,我們定義一個私有的方法進行註冊。

postProcessBeanFactory()是bean配置的工廠方法,在這個方法中可以獲取到我們所有在postProcessBeanDefinitionRegistry方法中註冊的所有bean,在這裡我們可以進行屬性的設定等操作。

//這裡可以設定屬性,例如

              BeanDefinitionbeanDefinition =beanFactory.getBeanDefinition("dataSourceA");

              MutablePropertyValuesmutablePropertyValues =beanDefinition.getPropertyValues();

              //加入屬性.

              mutablePropertyValues.addPropertyValue("driverClassName","com.mysql.jdbc.Driver");

              mutablePropertyValues.addPropertyValue("url","jdbc:mysql://localhost:3306/test");

              mutablePropertyValues.addPropertyValue("username","root");

              mutablePropertyValues.addPropertyValue("password","123456");

測試程式碼:

以直接注入我們的物件,對於同樣介面的我們需要指定name

package com.kfit.config;

import org.kfit.service.HelloService;

importorg.springframework.beans.factory.annotation.Qualifier;

importorg.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import com.kfit.demo.Shanhy;

@Configuration

publicclass MyConfig {

       /**

        * 這裡只是測試使用,沒有實際的意義.

        */

       @Bean(name="testHelloService")

       public HelloServicefilterRegistrationBean(@Qualifier("shanhyB") Shanhyshanhy){

              HelloServicehelloService =new HelloService();

        shanhy.display();

        // 其它處理程式碼.

        returnhelloService;

       }

}

使用@Resource 或者 @Autowired並指定@Qualifier 也可以:

package com.kfit.controller;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;

importorg.springframework.beans.factory.annotation.Qualifier;

importorg.springframework.web.bind.annotation.RequestMapping;

importorg.springframework.web.bind.annotation.RestController;

import com.kfit.demo.Shanhy;

/**

 *

 *@author Angel(QQ:412887952)

 *@version v.0.1

 */

@RestController

publicclass HelloController {

       @Resource(name = "shanhyA")

       private ShanhyshanhyA;

       @Autowired

       @Qualifier("shanhyB")

       private ShanhyshanhyB;

       @RequestMapping("/test")

       public String test(){

              shanhyA.display();

              shanhyB.display();

              return"test";

       }

}

在原始碼中由於程式碼有此係列教程別的章節的程式碼,請自行忽略閱讀,給大家造成的不變請諒解。

這裡有點經驗要說一下,在 @Configuration 中,不能使用注入屬性的方式注入,只能通過引數的方式注入,其原因就是@Configuration的類一開始便被載入,此時你想進行屬性注入,需要注入的bean物件都還不存在。

下面的程式碼片段也可以註冊Bean,比較簡單:

@Configuration

@Import(Registrar.class)

publicclassTestConfig {

}

classRegistrarimplementsImportBeanDefinitionRegistrar {

privatestaticfinal String BEAN_NAME ="myTestBean";

    @Override

publicvoid registerBeanDefinitions(AnnotationMetadataimportingClassMetadata, BeanDefinitionRegistry registry) {

if(!registry.containsBeanDefinition(BEAN_NAME)) {

           GenericBeanDefinition beanDefinition =newGenericBeanDefinition();

           beanDefinition.setBeanClass(ExamplePostProcessor.class);

           beanDefinition.setSynthetic(true);

           registry.registerBeanDefinition(BEAN_NAME, beanDefinition);

        }

    }

}

Spring Boot 系列視訊】

視訊&交流平臺:

http://study.163.com/course/introduction.htm?courseId=1004329008

http://412887952-qq-com.iteye.com/blog/2321532

網易雲課堂視訊最新更新

第十一章 Spring Boot 日誌

1、spring boot日誌—理論

2、Spring Boot日誌-logback

3、Spring Boot日誌-log4j2

第十二章 Spring Boot 知識點2

1、spring boot 服務配置和部署

2、Spring Boot 定製URL匹配規則

歷史章節

第一章 快速開始

1、Spring Boot之Hello World

2、Spring Boot之Hello World訪問404

第二章 Spring Boot之JSON

1、spring boot返回json資料

2、Spring Boot完美使用FastJson解析JSON資料

第三章 Spring Boot熱部署

1、Spring Boot熱部署(springloader)

2、springboot + devtools(熱部署)

第四章 Spring Boot資料庫

1、Spring Boot JPA/Hibernate/Spring Data概念

2、Spring Boot JPA-Hibernate

3、Spring Boot Spring Data JPA介紹

4、Spring Boot JdbcTemplate

5、Spring Boot整合MyBatis

第五章 web開發

1、全域性異常捕捉

2、配置server資訊

3、spring boot使用thymeleaf

4、Spring Boot 使用freemarker

5、Spring Boot新增JSP支援

第六章 定時任務

1、Spring Boot定時任務

2、Spring Boot 定時任務升級篇(動態修改cron引數)

3、Spring Boot 定時任務升級篇(動態新增修改刪除定時任務)

4、Spring Boot 定時任務升級篇(叢集/分散式下的定時任務說明)

5、Spring Boot Quartz介紹

6、Spring Boot Quartz在Java Project中使用

7、Spring Boot 整合Quartz普通使用

8、Spring Boot 整合Quartz升級版

9、Spring Boot 整合Quartz二次升級版

10、Spring Boot 整合Quartz-Job如何自動注入Spring容器託管的物件

第七章 Spring Boot MyBatis升級篇

1、Spring Boot MyBatis升級篇-註解

2、Spring Boot MyBatis升級篇-註解-自增ID

3、Spring Boot MyBatis升級篇-註解-增刪改查

4、Spring Boot MyBatis升級篇-註解-分頁查詢

5、Spring Boot MyBatis升級篇-註解-分頁PageHelper不生效

6、Spring Boot MyBatis升級篇-註解- mybatic insert異常:BindingException: Parameter 'name' not found

7、Spring Boot MyBatis升級篇-註解- #和$符號特別篇

8、Spring Boot MyBatis升級篇-註解[email protected]

9、Spring Boot MyBatis升級篇-註解-動態SQL(if test)-方案一:<script>

10、Spring Boot MyBatis升級篇-註解-動態SQL(if test)-方案二:@Provider

11、Spring Boot MyBatis升級篇-註解-動態SQL-引數問題

12、Spring Boot MyBatis升級篇-註解-特別篇:@MapperScan和@Mapper

13、Spring Boot MyBatis升級篇-XML

14、Spring Boot MyBatis升級篇-XML-自增ID

15、Spring Boot MyBatis升級篇-XML-增刪改查

16、Spring Boot MyBatis升級篇-XML-分頁查詢

17、Spring Boot MyBatis升級篇-XML-分頁PageHelper不生效

18、Spring Boot MyBatis升級篇-XML-動態SQL(if test)

19、Spring Boot MyBatis升級篇-XML-註解-初嘗試

20、Spring Boot MyBatis升級篇- pagehelper替換為pagehelper-spring-boot-starter

第八章 Spring Boot 知識點1

1、Spring Boot 攔截器HandlerInterceptor

2、Spring Boot啟動載入資料CommandLineRunner

3、Spring Boot環境變數讀取和屬性物件的繫結

4、Spring Boot使用自定義的properties

5、Spring Boot使用自定義的properties

6、Spring Boot使用@SpringBootApplication

7、Spring Boot 監控和管理生產環境

第十章 Spring Boot 打包部署

1、Spring Boot打包部署((提供Linux的sh檔案))

第十一章 Spring Boot 日誌

1、spring boot日誌—理論

2、Spring Boot日誌-logback

3、Spring Boot日誌-log4j2


相關推薦

41. Spring Boot 使用Java程式碼建立Bean註冊Spring開始Spring Boot

【視訊&交流平臺】 http://study.163.com/course/introduction.htm?courseId=1004329008&utm_campaign=commission&utm_source=40000000

43. Spring Boot動態資料來源(多資料來源自動切換)開始Spring Boot

【視訊&交流平臺】 http://study.163.com/course/introduction.htm?courseId=1004329008&utm_campaign=commission&utm_source=40000000

Spring Boot 使用Java程式碼建立Bean註冊Spring

從 Spring3.0 開始,增加了一種新的途經來配置Bean Definition,這就是通過 Java Code 配置 Bean Definition。 與Xml和Annotation兩種配置方式不同點在於: 前兩種Xml和Annotation的配置方式

資料新增非同步解析重新整理大資料量redis (——)(三)Spring Boot普通類呼叫bean開始Spring Boot

部落格分類:  從零開始學Spring Boot 從零開始學Spring BootSpring Boot普通類呼叫bean    【視訊&交流平臺】 à SpringBoot視訊 http://stu

17、Spring Boot普通類呼叫bean開始Spring Boot

【視訊&交流平臺】 http://study.163.com/course/introduction.htm?courseId=1004329008&utm_campaign=commission&utm_source=40000000

Spring Boot使用模板freemarker開始Spring Boot(轉)

dep demo attach macro 使用 doctype com 地址 2016年 視頻&交流平臺:à SpringBoot網易雲課堂視頻http://study.163.com/course/introduction.htm?courseId=10

33. Spring Boot 監控和管理生產環境開始Spring Boot

【視訊&交流平臺】 http://study.163.com/course/introduction.htm?courseId=1004329008&utm_campaign=commission&utm_source=40000000

(33)Spring Boot 監控和管理生產環境開始Spring Boot

spring-boot-actuator模組提供了一個監控和管理生產環境的模組,可以使用http、jmx、ssh、telnet等拉管理和監控應用。審計(Auditing)、 健康(health)、資料採集(metrics gathering)會自動加入到應用裡面。 首先,寫

8. 使用JPA儲存資料開始Spring Boot

【視訊&交流平臺】 http://study.163.com/course/introduction.htm?courseId=1004329008&utm_campaign=commission&utm_source=40000000

103. Spring Boot Freemarker特別篇之contextPath開始Spring Boot

需求緣起:有人在群裡@我:請教群主大神一個問題,spring boot  + freemarker 怎麼獲取contextPath 頭疼死我了,網上沒一個靠譜的 。我就看看之前部落格中的 【Spring Boot使用模板freemarker】好像確實沒有介紹到在.ftl檔案

31. Spring Boot匯入XML配置開始Spring Boot

【視訊&交流平臺】 http://study.163.com/course/introduction.htm?courseId=1004329008&utm_campaign=commission&utm_source=40000000

2. Spring Boot返回json資料開始Spring Boot

【視訊&交流平臺】 http://study.163.com/course/introduction.htm?courseId=1004329008&utm_campaign=commission&utm_source=40000000

35. Spring Boot整合Redis實現快取機制開始Spring Boot

【視訊&交流平臺】 http://study.163.com/course/introduction.htm?courseId=1004329008&utm_campaign=commission&utm_source=40000000

51. spring boot屬性檔案之多環境配置開始Spring Boot

【視訊&交流平臺】 http://study.163.com/course/introduction.htm?courseId=1004329008&utm_campaign=commission&utm_source=40000000

(27)Spring Boot Junit單元測試開始Spring Boot

Junit這種老技術,現在又拿出來說,不為別的,某種程度上來說,更是為了要說明它在專案中的重要性。 那麼先簡單說一下為什麼要寫測試用例 1. 可以避免測試點的遺漏,為了更好的進行測試,可以提高測試效率 2. 可以自動測試,可以在專案打包前進行測試校驗 3. 可以及時發現因為

40. springboot + devtools(熱部署)開始Spring Boot

【視訊&交流平臺】 http://study.163.com/course/introduction.htm?courseId=1004329008&utm_campaign=commission&utm_source=40000000

104. Spring Boot 啟動流程分析第三篇開始Spring Boot

問題的提出:Spring Boot不像spring需要定義xml檔案檔案,那麼spring boot是如何在沒有配置檔案的情況下為我們啟動一個完整的WEB工程的呢。我們先@SpringBootApplication開始分析下這個啟動流程,原始碼取自:1.4.1.RELEAS

(4)Spring Boot完美使用FastJson解析JSON資料開始Spring Boot

個人使用比較習慣的json框架是fastjson,所以spring boot預設的json使用起來就很陌生了,所以很自然我就想我能不能使用fastjson進行json解析呢? 引入fastjson依賴庫:   <dependencies>         <

65.什麼是IOC?開始Spring Boot

【從零開始學習Spirng Boot—常見異常彙總】        這個小節吧,是無意當中看了一篇文章,覺得介紹的特別好,引用到我的部落格中,讓大家也樂下。那麼他是怎麼解說IOC的呢?看如下: 套用好萊塢的一句名言就是:你呆著別動,到時我會找你。  什麼意思呢?就好比一個皇帝和太監  有一天皇

78. Spring Boot完美使用FastJson解析JSON資料開始Spring Boot

【原創文章,轉載請註明出處】        個人使用比較習慣的json框架是fastjson,所以spring boot預設的json使用起來就很陌生了,所以很自然我就想我能不能使用fastjson進行json解析呢? 引入fastjson依賴庫:   <depen