免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
Spring IOC 特性有哪些,不會讀不懂源碼!


作者:小傅哥
博客:https://bugstack.cn

沉淀、分享、成長,讓自己和他人都能有所收獲!😄

一、前言

多線程、鎖、JVM調(diào)優(yōu),都背出花啦,怎么一寫代碼還是亂糟糟?

為什么這些無論從書本、課堂、面試都顯得非常重要的知識,但是在實(shí)際的編程中沒有提升你的編碼能力呢?

首先這些這些知識在實(shí)際的互聯(lián)網(wǎng)業(yè)務(wù)開發(fā)中,幾乎是不常用的,幾乎有鎖和多線程的場景,為了性能的提升也基本都是采用分布式設(shè)計(jì)和實(shí)現(xiàn)了。而這些看上去很有技術(shù)含量的知識多數(shù)都被包裝在非業(yè)務(wù)邏輯功能的組件中,而程序員在做業(yè)務(wù)開發(fā)時(shí)候幾乎是關(guān)心不到。所以會了這些也幾乎不太可能就把你的編碼能提升起來,多數(shù)提升的是你在查復(fù)雜bug時(shí)候有一臂之力。

就像會漢字就能寫出詩詞歌賦嗎?懂RGB就能繪出山河大川嗎?能蹦跳就可以舞出搖曳生姿嗎?那都是不可能的,不要想著屁股圍噶補(bǔ)就說會武術(shù)!

如果真的想把代碼寫好,就要一點(diǎn)點(diǎn)從積累數(shù)據(jù)結(jié)構(gòu)和算法邏輯(不只是機(jī)械式的刷幾道題就算了。你不理解為什么,刷再多也只是徒勞),接下來要做的是對設(shè)計(jì)模式和架構(gòu)設(shè)計(jì)的理解,最終是不斷的運(yùn)用和總結(jié)。在這個(gè)過程你會接觸到業(yè)務(wù)、產(chǎn)品、運(yùn)營,編碼只是最后的具體實(shí)現(xiàn),并不是全流程中最重要的一部分,與編碼相比更重要的是邏輯設(shè)計(jì)。

二、面試題

謝飛機(jī),小記!,這次放假一遍擼串一遍被Spring,嘿嘿,檢驗(yàn)成果面試去!

面試官:飛機(jī),今天準(zhǔn)備咋樣,上次問你的都學(xué)會了嗎?

謝飛機(jī):@Resource 是 JDK javax.annotation.Resource 提供的注解,哈哈哈哈哈,另外也學(xué)習(xí)了Bean的注入。

面試官:挺好記住了一些,那你在做 Bean 注入學(xué)習(xí)的時(shí)候,有注意到 Spring IOC 的特性嗎,你都用到了什么?

謝飛機(jī):嗯,用到 Bean 的配置、BeanDefinitionRegistryPostProcessor 對 Bean 的定義、還有 FactoryBean

面試官:好,那今天再和你聊聊,alias、autowire、depends-on、factory-method、lookup-method等,實(shí)踐驗(yàn)證下看看它們是怎么應(yīng)用的。

三、SpringIOC 特性

IOC(Inversion of Control),控制反轉(zhuǎn)的核心思想在于,資源的使用不由使用各自管理,而是交給不使用資源的第三方進(jìn)行管理。這樣的好處是資源是集中管理的,可配置、易維護(hù),同時(shí)也降低了雙方的依賴度做到了低耦合。

早在1988年,Ralph E. Johnson & Brian Foote在論文《Designing Reusable Classes》

One important characteristic of a framework is that the methods defined by the user to tailor the framework will often be called from within the framework itself, rather than from the user’s application code.
The framework often plays the role of the main program in coordinating and sequencing application activity.
This inversion of control gives frameworks the power to serve as extensible skeletons. The methods supplied by the user tailor the generic algorithms defined in the framework for a particular application.

接下來就給大家介紹一下 IOC 的一些核心特性,因?yàn)檫@些內(nèi)容不僅是面試考點(diǎn),也是在開發(fā)中間件或者小組件時(shí)需要用到的功能類,概括如下:

1. xml 配置

1.1 alias

測試類

public class UserService {

    private UserDao userDao;

    public UserService() {
        System.out.println("我被初始化了,UserService");
    }

    // ...get/set

}

xml配置

<bean id="userService" class="org.itstack.interview.UserService"/>
<!-- 起個(gè)別名 -->
<alias name="userService" alias="userService-alias01"/>
<!-- 別名的別名 -->
<alias name="userService-alias01" alias="userService-alias02"/>

單元測試

@Test
public void test_alias() {
    BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config-alias.xml");
    logger.info("獲取 Bean:{}", beanFactory.getBean("userService"));
    logger.info("獲取 Bean 通過別名:{}", beanFactory.getBean("userService-alias01"));
    logger.info("獲取 Bean 通過別名的別名:{}", beanFactory.getBean("userService-alias02"));
}

測試結(jié)果

23:01:29.872 [main] INFO  org.itstack.interview.test.ApiTest - 獲取 Bean:org.itstack.interview.UserService@2a40cd94
23:01:29.872 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'userService'
23:01:29.872 [main] INFO  org.itstack.interview.test.ApiTest - 獲取 Bean 通過別名:org.itstack.interview.UserService@2a40cd94
23:01:29.872 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'userService'
23:01:29.872 [main] INFO  org.itstack.interview.test.ApiTest - 獲取 Bean 通過別名的別名:org.itstack.interview.UserService@2a40cd94

  • 目的:用于給 Bean 起別名
  • 使用:在 xml 配置里我們可以給一個(gè) Bean 起個(gè)別名,還可以給別名起一個(gè)新的別名。

1.2 autowire

測試類

public class UserDao {
    public UserDao() {
        System.out.println("我被初始化了,UserDao");
    }
}

xml配置

<bean id="userDao" class="org.itstack.interview.UserDao"/>

<!-- 手動配置依賴 -->
<bean id="userService-by-property" class="org.itstack.interview.UserService">
    <property name="userDao" ref="userDao"/>
</bean>

<!-- 自動配置依賴 -->
<bean id="userService-by-autowire" class="org.itstack.interview.UserService" autowire="byName"/>

單元測試

@Test
public void test_autowire() {
    BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config-autowire.xml");
    logger.info("獲取 Bean by 手動配置依賴:{}", beanFactory.getBean("userService-by-property"));
    logger.info("獲取 Bean by 自動配置依賴:{}", beanFactory.getBean("userService-by-autowire"));
}

測試結(jié)果

23:05:55.501 [main] INFO  org.itstack.interview.test.ApiTest - 獲取 Bean by 手動配置依賴:org.itstack.interview.UserService@679b62af
23:05:55.501 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'userService-by-autowire'
23:05:55.501 [main] INFO  org.itstack.interview.test.ApiTest - 獲取 Bean by 自動配置依賴:org.itstack.interview.UserService@5cdd8682

  • 目的:autowire 用于把類中的屬性注入交給 Spring 管理
  • 使用:在 xml 配置中,有兩種方式分別是:手動配置依賴、自動配置依賴,手動的大家基本很常用,自動的配置一般可能更多的對于注解的使用。其實(shí)這里的 autowire 和注解有一樣的作用,autowire 幾個(gè)可選項(xiàng),byName、byType、constructor 等。

1.3 factory-method

測試類

public class StaticFactoryBean {

    static public UserDao getUserDaoByStatic(){
        return new UserDao();
    }

}

xml配置

<bean id="staticFactory-method" class="org.itstack.interview.StaticFactoryBean" factory-method="getUserDaoByStatic"/>

單元測試

@Test
public void test_factory_method() {
    BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config-factory-method.xml");
    logger.info("獲取 Bean:{}", beanFactory.getBean("staticFactory-method"));
}

測試結(jié)果

23:15:28.950 [main] INFO  org.itstack.interview.test.ApiTest - 獲取 Bean:org.itstack.interview.UserDao@588df31b
23:15:28.950 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'staticFactory-bean'

  • 目的:標(biāo)識靜態(tài)工廠的工廠方法(工廠方法是靜態(tài)的)
  • 使用:核心在于 xml 配置中添加 factory-method="getUserDaoByStatic",這樣就可以在初始化時(shí)候調(diào)用對應(yīng)靜態(tài)方法的實(shí)例化內(nèi)容。

1.4 factory-bean

測試類

public class StaticFactoryBean {
    public UserDao getUserDao(){
        return new UserDao();
    }
}

xml配置

<bean id="staticFactory" class="org.itstack.interview.StaticFactoryBean"/>
<bean id="staticFactory-bean" factory-bean="staticFactory" factory-method="getUserDao"/>

單元測試

@Test
public void test_factory_bean_method() {
    BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config-factory-method.xml");
    logger.info("獲取 Bean:{}", beanFactory.getBean("staticFactory-bean"));
}

測試結(jié)果

23:15:28.950 [main] INFO  org.itstack.interview.test.ApiTest - 獲取 Bean:org.itstack.interview.UserDao@33b37288

  • 目的:factory-bean,實(shí)例化工廠類
  • 使用:factory-bean、factory-method 需要配合使用,factory-method="getUserDao" 調(diào)用的是對應(yīng)的費(fèi)靜態(tài)方法返回實(shí)例化結(jié)果。

1.5 depends-on

xml配置

<bean id="userService" class="org.itstack.interview.UserService" depends-on="userDao"/>
<bean id="userDao" class="org.itstack.interview.UserDao"/>

單元測試

@Test
public void test_depends_on() {
    BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config-depends-on.xml");
    logger.info("獲取 Bean:{}", beanFactory.getBean(UserService.class, "userService").getUserDao());
}

測試結(jié)果

我被初始化了,UserDao
我被初始化了,UserService
23:24:14.678 [main] INFO  org.itstack.interview.test.ApiTest - 獲取 Bean:org.itstack.interview.UserDao@45afc369

  • 目的:處理依賴初始化順序問題
  • 使用:如果不使用 depends-on="userDao",那么按照 Spring 的配置最先初始化的是 UserService,當(dāng)你有需要處理初始化依賴時(shí)則需要使用到這個(gè)配置。

1.6 lookup-method & ApplicationContextAware

測試類

public class UserDaoProvider implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    public UserDao getUserDao() {
        return applicationContext.getBean("userDao", UserDao.class);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

}

xml配置

<bean id="userDao" class="org.itstack.interview.UserDao" scope="prototype"/>
<bean id="provider" class="org.itstack.interview.UserDaoProvider"/>

單元測試

@Test
public void test_lookup_method() {
    BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config-lookup-method.xml");
    logger.info("獲取 Bean:{}", beanFactory.getBean(UserDaoProvider.class, "provider").getUserDao());
    logger.info("獲取 Bean:{}", beanFactory.getBean(UserDaoProvider.class, "provider").getUserDao());
}

測試結(jié)果

我被初始化了,UserDao
16:29:25.813 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'userDao'
16:29:25.813 [main] INFO  org.itstack.interview.test.ApiTest - 獲取 Bean:org.itstack.interview.UserDao@1188e820
16:29:25.813 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'userDao'
我被初始化了,UserDao
16:29:25.814 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'userDao'
16:29:25.814 [main] INFO  org.itstack.interview.test.ApiTest - 獲取 Bean:org.itstack.interview.UserDao@2f490758

  • 目的:獲取單例下的原型模式,每次獲取都要有新的對象產(chǎn)生。
  • 使用:其實(shí)核心在于 ApplicationContextAware 的使用和 scope="prototype" 配置,Spring 內(nèi)部實(shí)現(xiàn)為使用 Cglib 方法,重新生成子類,重寫配置的方法和返回對象,達(dá)到動態(tài)改變的效果。

2. 接口類

2.1 FactoryBean

測試類

public class MyFactoryBean implements FactoryBean<UserDao> {

    @Override
    public UserDao getObject() throws Exception {
        return new UserDao();
    }

    @Override
    public Class<?> getObjectType() {
        return UserDao.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
    
}

xml配置

<bean id="userDao" class="org.itstack.interview.MyFactoryBean"/>

單元測試

@Test
public void test_factory_bean() {
    BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config-factory-bean.xml");
    logger.info("獲取 Bean:{}", beanFactory.getBean("userDao"));
}

測試結(jié)果

23:36:19.339 [main] INFO  org.itstack.interview.test.ApiTest - 獲取 Bean:org.itstack.interview.UserDao@3bd94634

  • 目的:用于生成 Bean 的 Bean,叫 FactoryBean
  • 使用:其實(shí)這個(gè)使用在上一章節(jié)關(guān)于 Bean 如何注入到 Spring 已經(jīng)提到過,在一些ORM框架、RPC-Starter等都有所應(yīng)用。

2.2 BeanPostProcessor

測試類

public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("初始化前:" + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("初始化后:" + beanName);
        return bean;
    }
    
}

xml配置

<bean id="beanPostProcessor" class="org.itstack.interview.MyBeanPostProcessor"/>
<bean id="userDao" class="org.itstack.interview.UserDao"/>

單元測試

@Test
public void test_bean_post_processor() {
    BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config-bean-post-processor.xml");
}

測試結(jié)果

初始化前:userDao
初始化后:userDao
16:38:32.686 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'userDao'

  • 目的:拿到 Bean 對象初始化前后的動作,做相應(yīng)的處理
  • 使用:BeanPostProcessor 是 Spring 框架的擴(kuò)展接口類,通過對這個(gè)接口的實(shí)現(xiàn),就可以在 Bean 實(shí)例化的過程中做相關(guān)的動作,比如攔截以后發(fā)布到注冊中心等。AOP 的操作也是通過 BeanPostProcessor 和 IOC 容器建立起聯(lián)系。

2.3 BeanFactoryAware

測試類

public class MyBeanFactoryAware implements BeanFactoryAware {
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        
    }
}

  • 目的:用于獲取運(yùn)行時(shí) Bean 的配置信息
  • 使用:BeanFactoryAware 的實(shí)現(xiàn)類可以拿到 beanFactory,也就獲取到了bean的上下文信息,此時(shí)你想獲取一些對象的屬性就非常容易了。

四、總結(jié)

  • 以上我們介紹了 Spring IOC 的常用配置特性和接口,雖然現(xiàn)在大家可能已經(jīng)很少會使用 xml 配置對象,基本都是注解的方式。但在這些注解的背后依然會有相應(yīng)的通用核心原理實(shí)現(xiàn),只有把這部分知識總結(jié)清楚并學(xué)習(xí)源碼,才能更好的理解注解的使用是如何處理這些配置的。
  • 關(guān)于接口的類使用,FactoryBean、BeanPostProcessor、BeanFactoryAware、ApplicationContextAware,在日常的業(yè)務(wù)流程開發(fā)中幾乎接觸不到,但如果要做一些核心的組件設(shè)計(jì)或者是中間件的開發(fā),就會使用的非常頻繁。如果對這部分知識的運(yùn)用不了解,可以參考:《SpringBoot 中間件設(shè)計(jì)和開發(fā)》
  • 后續(xù)會圍繞這些知識點(diǎn)來給大家介紹一些源碼的學(xué)習(xí)以及應(yīng)用層的處理,Bean的創(chuàng)建、循環(huán)依賴的三級緩存解決方案等。也希望大家在學(xué)習(xí)的過程中要多總結(jié)、思考、記錄,一點(diǎn)點(diǎn)的把知識棧建設(shè)完整。

五、系列推薦

  • 小伙伴美團(tuán)一面的分享和分析
  • 你說,怎么把Bean塞到Spring容器?
  • 除了JDK、CGLIB,還有3種類代理方式?面試又卡住!
  • 半年招聘篩選了400+份簡歷,告訴你怎么寫容易被撩!
  • SpringBoot 中間件設(shè)計(jì)和開發(fā)
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
UC頭條:[面試必問]Spring核心之控制反轉(zhuǎn)(IOC)
《Spring3.X企業(yè)應(yīng)用開發(fā)實(shí)戰(zhàn)》學(xué)習(xí)筆記
Spring中BeanFactory與ApplicationContext的區(qū)別
Spring內(nèi)核研究-通過工廠注入
幾種獲得spring里注冊Bean的方法
springLookup方法注入
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服