關(guān)于手動(dòng)注入bean的幾種方式

比如要注入Student這個(gè)類

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
    private Integer id = 100;

    private String name = "zhangsan";

    private Integer age = 20;

    private Boolean sex = true;
}

第一種

  • 使用@Bean注解友驮,這種方式是最簡單的方式;
    示例:
@Configuration
public class StudentConfig {
    @Bean
    public Student getStudent() {
        return new Student();
    }
}
  • 測試:
@SpringBootTest
public class TestDemoApplicationTests {

    @Autowired
    private Student student;

    @Test
    void getBean() {
        System.out.println(student);
    }
}

結(jié)果:


image.png

第二種

  • 通過實(shí)現(xiàn)ImportSelector接口和結(jié)合@Import注解來注入驾锰;
    這種方式其實(shí)也是SpringBoot的自動(dòng)注入方式卸留,這里只是簡單實(shí)現(xiàn)。
  • StudentImportSelector
public class StudentImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        String[] str = {"com.chitang.domain.Student"};
        return str;
    }
}
@Configuration
@Import(StudentImportSelector.class)
public class StudentConfiguration {
}
  • 通過@Import注解進(jìn)行導(dǎo)入椭豫。

  • 看看SpringBoot是怎么做的耻瑟。


    image.png
  • 順便對比一下SpringBoot相應(yīng)的實(shí)現(xiàn)方式,不相關(guān)的代碼省略掉了赏酥。

public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
        ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        }
        AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
        return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
    }
}

這里AutoConfigurationImportSelector類實(shí)現(xiàn)了DeferredImportSelector接口喳整,這個(gè)接口其實(shí)就是ImportSelector的子接口,兩者有點(diǎn)區(qū)別裸扶,這里不做解釋框都。
看一下selectImports方法中最后return的時(shí)候StringUtils.toStringArray(autoConfigurationEntry.getConfigurations()),返回的就是一個(gè)String類型的數(shù)組呵晨,數(shù)組里面就是需要自動(dòng)裝配類的路徑魏保。所以在我自己的selectImports方法中,就直接返回了Student的路徑摸屠。

  • 測試


    image.png

第三種

  • 通過實(shí)現(xiàn)ImportBeanDefinitionRegistrar接口和結(jié)合@Import注解來注入谓罗。
public class StudentRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(Student.class);
        registry.registerBeanDefinition(Student.class.getSimpleName(), beanDefinitionBuilder.getBeanDefinition());
    }
}
@Configuration
//@Import(StudentImportSelector.class)
@Import(StudentRegistrar.class)
public class StudentConfiguration {
}
  • 使用方式和第二種一樣。
  • 測試


    image.png
  • 來看看這種方式在源碼中的實(shí)踐吧季二!
  • 點(diǎn)進(jìn)ImportBeanDefinitionRegistrar接口中檩咱,看一下他的實(shí)現(xiàn)類。


    image.png
  • 我們點(diǎn)進(jìn)一個(gè)稍微熟悉的實(shí)現(xiàn)類中去看看吧胯舷,就BeanPostProcessorsRegistrar吧刻蚯。
public static class BeanPostProcessorsRegistrar implements ImportBeanDefinitionRegistrar, BeanFactoryAware {

        private ConfigurableListableBeanFactory beanFactory;

        @Override
        public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
            if (beanFactory instanceof ConfigurableListableBeanFactory) {
                this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
            }
        }

        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
                BeanDefinitionRegistry registry) {
            if (this.beanFactory == null) {
                return;
            }
            registerSyntheticBeanIfMissing(registry, "webServerFactoryCustomizerBeanPostProcessor",
                    WebServerFactoryCustomizerBeanPostProcessor.class,
                    WebServerFactoryCustomizerBeanPostProcessor::new);
            registerSyntheticBeanIfMissing(registry, "errorPageRegistrarBeanPostProcessor",
                    ErrorPageRegistrarBeanPostProcessor.class, ErrorPageRegistrarBeanPostProcessor::new);
        }

        private <T> void registerSyntheticBeanIfMissing(BeanDefinitionRegistry registry, String name,
                Class<T> beanClass, Supplier<T> instanceSupplier) {
            if (ObjectUtils.isEmpty(this.beanFactory.getBeanNamesForType(beanClass, true, false))) {
                RootBeanDefinition beanDefinition = new RootBeanDefinition(beanClass, instanceSupplier);
                beanDefinition.setSynthetic(true);
                registry.registerBeanDefinition(name, beanDefinition);
            }
        }

    }

都是在registerBeanDefinitions方法中進(jìn)行注入的,只是他這里的方式比較完善桑嘶,我寫的比較簡單芦倒。大家如果愿意的話,可以把這一段直接copy到自己需要用的地方不翩,都不用改的兵扬,哈哈。

  • 再來看看口蝠,他怎么讓這個(gè)類生效的呢器钟?往上劃,滑到最上面去妙蔗。


    image.png
  • 最終也是使用@Import注解來干的傲霸。
    細(xì)心的小伙伴可能會(huì)發(fā)現(xiàn),有個(gè)熟悉的名字出現(xiàn)了。


    image.png
  • 是的昙啄,SpringBoot自帶的3個(gè)web容器也是在這里導(dǎo)入的穆役。

  • 來拓展一下吧,點(diǎn)進(jìn)EmbeddedTomcat類中梳凛,發(fā)現(xiàn)它也是個(gè)靜態(tài)內(nèi)部類耿币。


    image.png
  • 她是想注入TomcatServletWebServerFactory這個(gè)類,那我們進(jìn)去看看韧拒。


    image.png

    這個(gè)類就不多說了淹接,我看看好玩的,這里的port叛溢,我們一直往上跟塑悼,一直到AbstractConfigurableWebServerFactory類中,最后發(fā)現(xiàn)楷掉,我們平常最熟悉的8080端口居然在這里待著厢蒜。


    image.png
  • 好了,這就是今天給大家分享的一些知識了烹植,拜拜郭怪。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市刊橘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌颂鸿,老刑警劉巖促绵,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異嘴纺,居然都是意外死亡败晴,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進(jìn)店門栽渴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來尖坤,“玉大人,你說我怎么就攤上這事闲擦÷叮” “怎么了?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵墅冷,是天一觀的道長纯路。 經(jīng)常有香客問我,道長寞忿,這世上最難降的妖魔是什么驰唬? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上叫编,老公的妹妹穿的比我還像新娘辖佣。我一直安慰自己,他們只是感情好搓逾,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布卷谈。 她就那樣靜靜地躺著,像睡著了一般恃逻。 火紅的嫁衣襯著肌膚如雪雏搂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天寇损,我揣著相機(jī)與錄音凸郑,去河邊找鬼。 笑死矛市,一個(gè)胖子當(dāng)著我的面吹牛芙沥,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播浊吏,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼而昨,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了找田?” 一聲冷哼從身側(cè)響起歌憨,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎墩衙,沒想到半個(gè)月后务嫡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡漆改,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年心铃,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片挫剑。...
    茶點(diǎn)故事閱讀 38,599評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡去扣,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出樊破,到底是詐尸還是另有隱情愉棱,我是刑警寧澤,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布哲戚,位于F島的核電站羽氮,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏惫恼。R本人自食惡果不足惜档押,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧令宿,春花似錦叼耙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至癞松,卻和暖如春爽撒,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背响蓉。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工硕勿, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人枫甲。 一個(gè)月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓源武,卻偏偏與公主長得像,于是被迫代替她去往敵國和親想幻。 傳聞我的和親對象是個(gè)殘疾皇子粱栖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內(nèi)容