SpringBoot Bean花式注解方法示例下篇
1.容器初始化完成后注入bean
import lombok.Data; import org.springframework.stereotype.Component; @Component("miao") @Data public class Cat { }
被注入的JavaBean
import org.springframework.context.annotation.Configuration; @Configuration public class Config5 { }
被加載的配置類
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import yi.beans.Cat; import yi.config.Config5; public class App2 { public static void main(String[] args) { AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(Config5.class); context.registerBean(Cat.class); String[] names = context.getBeanDefinitionNames(); for (String name : names) { System.out.println(name); } } }
在加載配置類的時(shí)候,普通的ApplicationContext不具備該功能。
可以看到其還具有掃描JavaBean注解的功能,直接把名字裝配了,沒(méi)有自定義名字的話就是類名首字母小寫(xiě)。
那么同一個(gè)實(shí)體類被加載多次會(huì)怎么樣呢?
import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.stereotype.Component; @Component("miao") @Data @NoArgsConstructor public class Cat { String shout; public Cat(String shout) { this.shout = shout; } }
import org.springframework.context.annotation.Configuration; @Configuration public class Config5 { }
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import yi.beans.Cat; import yi.config.Config5; public class App2 { public static void main(String[] args) { AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(Config5.class); context.registerBean(Cat.class,"1"); context.registerBean(Cat.class,"2"); context.registerBean(Cat.class,"3"); Cat miao = context.getBean("miao",Cat.class); System.out.println(miao.getShout()); } }
可以看到如果被加載多次的話,后面會(huì)覆蓋前面的。
這個(gè)和我們?cè)谂渲脃ml文件屬性時(shí)有異曲同工之妙,配置了就是你的配置,沒(méi)有配置就是默認(rèn)的,你的配置會(huì)覆蓋默認(rèn)的配置,其中那些配置背后就是一個(gè)一個(gè)的bean對(duì)象罷了。
2.導(dǎo)入源的編程式處理
import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.stereotype.Component; @Component("miao") @Data @NoArgsConstructor @AllArgsConstructor public class Cat { String shout; }
import org.springframework.context.annotation.ImportSelector; import org.springframework.core.type.AnnotationMetadata; public class MyImportSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { return new String[]{"yi.beans.Cat"}; } }
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import yi.beans.MyImportSelector; @Configuration @Import(MyImportSelector.class) public class Config5 { }
import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import yi.config.Config5; public class App2 { public static void main(String[] args) { ApplicationContext context=new AnnotationConfigApplicationContext(Config5.class); String[] names = context.getBeanDefinitionNames(); for (String name : names) { System.out.println(name); } } }
可以看到注冊(cè)了bean,并且還識(shí)別到了注解的value值。
不過(guò)這種方式還僅不于此,還可以做很多判定。
import org.springframework.context.annotation.ImportSelector; import org.springframework.core.type.AnnotationMetadata; public class MyImportSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { boolean b = annotationMetadata.hasAnnotation("org.springframework.context.annotation.Configuration"); if (b){ //判斷是否包含這個(gè)注解 return new String[]{"yi.beans.Cat"}; }else { return new String[]{"yi.beans.Dog"}; } } }
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import yi.beans.MyImportSelector; //@Configuration @Import(MyImportSelector.class) public class Config5 { }
import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import yi.beans.Cat; import yi.config.Config5; public class App2 { public static void main(String[] args) { ApplicationContext context=new AnnotationConfigApplicationContext(Config5.class); String[] names = context.getBeanDefinitionNames(); for (String name : names) { System.out.println(name); } } }
可以看到,我們通過(guò)API可以達(dá)到多種多樣的效果,不僅有查看注解是否存在啊,還能獲取注解的所有參數(shù)等等。
@Configuration注解如果不被@ComponentScan掃描的話,直接被容器加載。是可以省略的,所以后面我是用@Import也是可以的。
3.bean裁定
import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.stereotype.Component; @Component("miao") @Data @NoArgsConstructor @AllArgsConstructor public class Cat { String shout; }
實(shí)體類我通過(guò)注解給它的bean賦了名字。
import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.type.AnnotationMetadata; public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { BeanDefinition beanDefinition= BeanDefinitionBuilder.rootBeanDefinition(Cat.class).getBeanDefinition(); registry.registerBeanDefinition("mao",beanDefinition); } }
AnnotationMetadata這個(gè)屬性我忽略了,因?yàn)檫@就是上一個(gè)定義bean的方式,可以通過(guò)元數(shù)據(jù)對(duì)其條件判斷,你可以結(jié)合到一塊。下面是定義了bean的名字,不過(guò)還有許多ApI你可以慢慢看有空的時(shí)候。
import org.springframework.context.annotation.Import; import yi.beans.MyImportBeanDefinitionRegistrar; @Import(MyImportBeanDefinitionRegistrar.class) public class Config5 { }
import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import yi.config.Config5; public class App2 { public static void main(String[] args) { ApplicationContext context=new AnnotationConfigApplicationContext(Config5.class); String[] names = context.getBeanDefinitionNames(); for (String name : names) { System.out.println(name); } } }
可以看到這里注解的value值被覆蓋了,在之前的方法中,一直都獲取的是注解的value值為bean的名字,由此說(shuō)明,這種方式的權(quán)限也開(kāi)放了不少。
拓展
那么如果我使用這種方式加載同一個(gè)bean加載了多次,是哪個(gè)生效呢?我來(lái)用接口模擬??梢园l(fā)現(xiàn)是最后一個(gè)被加載的在生效??赡苡腥藭?huì)疑問(wèn),為什么bean名字一樣,編譯時(shí)不報(bào)異常呢?
因?yàn)橐粋€(gè)項(xiàng)目是分布式的情況下,一個(gè)配置bean可能會(huì)被多個(gè)人修改,需要確保這些bean能夠覆蓋達(dá)到刷新的效果,我猜的,不一定對(duì)。
public interface BookService { void check(); }
import yi.beans.BookService; public class BookServiceImpl1 implements BookService { @Override public void check() { System.out.println("書(shū)籍是人類進(jìn)步的階梯"); } }
import yi.beans.BookService; public class BookServiceImpl2 implements BookService { @Override public void check() { System.out.println("書(shū)籍是人類進(jìn)步的階梯"); } }
import yi.beans.BookService; public class BookServiceImpl3 implements BookService { @Override public void check() { System.out.println("書(shū)籍是人類進(jìn)步的階梯"); } }
import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.type.AnnotationMetadata; import yi.beans.impl.BookServiceImpl1; public class MyImportBeanDefinitionRegistrar1 implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { BeanDefinition beanDefinition= BeanDefinitionBuilder.rootBeanDefinition(BookServiceImpl1.class).getBeanDefinition(); registry.registerBeanDefinition("bookService",beanDefinition); } }
import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.type.AnnotationMetadata; import yi.beans.impl.BookServiceImpl2; public class MyImportBeanDefinitionRegistrar2 implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { BeanDefinition beanDefinition= BeanDefinitionBuilder.rootBeanDefinition(BookServiceImpl2.class).getBeanDefinition(); registry.registerBeanDefinition("bookService",beanDefinition); } }
import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.type.AnnotationMetadata; import yi.beans.impl.BookServiceImpl3; public class MyImportBeanDefinitionRegistrar3 implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { BeanDefinition beanDefinition= BeanDefinitionBuilder.rootBeanDefinition(BookServiceImpl3.class).getBeanDefinition(); registry.registerBeanDefinition("bookService",beanDefinition); } }
import org.springframework.context.annotation.Import; import yi.beans.*; @Import({MyImportBeanDefinitionRegistrar1.class, MyImportBeanDefinitionRegistrar2.class, MyImportBeanDefinitionRegistrar3.class}) public class Config5 { }
import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import yi.beans.BookService; import yi.config.Config5; public class App2 { public static void main(String[] args) { ApplicationContext context=new AnnotationConfigApplicationContext(Config5.class); String[] names = context.getBeanDefinitionNames(); for (String name : names) { System.out.println(name); } BookService bookService = context.getBean("bookService", BookService.class); System.out.println(bookService.getClass()); } }
4.最終裁定
基于第七種方式,我們要是就是想要加載某個(gè)bean,又不想被其他人的覆蓋該怎么辦呢?也就是說(shuō)我們這個(gè)類無(wú)論加載到哪個(gè)位置,都不會(huì)被覆蓋。請(qǐng)看第八種方式。
在第七種拓展的基礎(chǔ)上,我們?cè)偌尤缦拢?/p>
import yi.beans.BookService; public class BookServiceImpl4 implements BookService { @Override public void check() { System.out.println("書(shū)籍是人類進(jìn)步的階梯"); } }
再加一個(gè)實(shí)現(xiàn)類。
import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; import yi.beans.impl.BookServiceImpl4; public class MyPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException { AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(BookServiceImpl4.class).getBeanDefinition(); beanDefinitionRegistry.registerBeanDefinition("bookService",beanDefinition); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { } }
通過(guò)BeanDefinition的注冊(cè)器實(shí)名bean,實(shí)現(xiàn)對(duì)bean的最終裁定。
import org.springframework.context.annotation.Import; import yi.beans.*; @Import({MyImportBeanDefinitionRegistrar1.class, MyImportBeanDefinitionRegistrar2.class, MyPostProcessor.class, MyImportBeanDefinitionRegistrar3.class,}) public class Config5 { }
可以看到,我將該類沒(méi)有放到最后。
import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import yi.beans.BookService; import yi.config.Config5; public class App2 { public static void main(String[] args) { ApplicationContext context=new AnnotationConfigApplicationContext(Config5.class); String[] names = context.getBeanDefinitionNames(); for (String name : names) { System.out.println(name); } BookService bookService = context.getBean("bookService", BookService.class); System.out.println(bookService.getClass()); } }
該類注冊(cè)的bean沒(méi)有被覆蓋耶。權(quán)限是不是更開(kāi)放了。bean的加載就到此為止。了解這些,springboot的源碼你讀起來(lái)就不會(huì)那么費(fèi)勁了。
到此這篇關(guān)于SpringBoot Bean花式注解方法示例下篇的文章就介紹到這了,更多相關(guān)SpringBoot Bean注解方法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot+WebSocket向前端推送消息的實(shí)現(xiàn)示例
WebSocket是一種在單個(gè)TCP連接上進(jìn)行全雙工通信的協(xié)議,允許服務(wù)器主動(dòng)向客戶端推送信息,同時(shí)也能從客戶端接收信息,本文主要介紹了SpringBoot+WebSocket向前端推送消息的實(shí)現(xiàn)示例,感興趣的可以了解一下2024-08-08詳解Java對(duì)象創(chuàng)建的過(guò)程及內(nèi)存布局
今天給大家?guī)?lái)的文章是Java對(duì)象創(chuàng)建的過(guò)程及內(nèi)存布局,文中有非常詳細(xì)的圖文示例及介紹,需要的朋友可以參考下2021-06-06SpringBoot項(xiàng)目請(qǐng)求不中斷動(dòng)態(tài)更新代碼的實(shí)現(xiàn)
在開(kāi)發(fā)中,有時(shí)候不停機(jī)動(dòng)態(tài)更新代碼熱部署是一項(xiàng)至關(guān)重要的功能,它可以在請(qǐng)求不中斷的情況下下更新代碼,這種方式不僅提高了開(kāi)發(fā)效率,還能加速測(cè)試和調(diào)試過(guò)程,本文將詳細(xì)介紹如何在 Spring Boot 項(xiàng)目在Linux系統(tǒng)中實(shí)現(xiàn)熱部署,特別關(guān)注優(yōu)雅關(guān)閉功能的實(shí)現(xiàn)2024-09-09Java使用pulsar-flink-connector讀取pulsar catalog元數(shù)據(jù)代碼剖析
這篇文章主要介紹了Java使用pulsar-flink-connector讀取pulsar catalog元數(shù)據(jù)代碼剖析,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-08-08Java中Cookie和Session詳解及區(qū)別總結(jié)
這篇文章主要介紹了Java中Cookie和Session詳解,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,感興趣的小伙伴可以參考一下2022-06-06Java客戶端通過(guò)HTTPS連接到Easysearch實(shí)現(xiàn)過(guò)程
這篇文章主要為大家介紹了Java客戶端通過(guò)HTTPS連接到Easysearch實(shí)現(xiàn)過(guò)程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11