首頁 > 軟體

關於@Configuration的作用說明

2023-01-04 14:00:44

一、問題描述

在專案中,通常都會設定一個或者多個加了@Configuration註解的設定類,那麼@Configuration這個註解到底有神馬作用勒?

@ComponentScan("com")
public class AppConfig {
    @Bean
    public TestDao testDao() {
        return new TestDao();
    }
}
public class Test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext acc = new AnnotationConfigApplicationContext(AppConfig.class);
    }
}
public class TestDao {
    public TestDao(){
        System.out.println("testDao");
    }

}

執行上面的程式碼,我們會發現當我們不加@Configuration這個註解的時候我們的TestDao 這個類還是還是會被範例化,也會列印testDao。我們的spring環境也可以正常執行。

那麼我們的@Configuration註解是來解決什麼問題的勒?

我們來看一下下面這段程式碼。當我們在AppConfig中有2個方法,而且第二個方法呼叫了第一個方法。

@ComponentScan("com")
public class AppConfig {

	@Bean
	public TestDao testDao() {
		return new TestDao();
	}

	@Bean
	public TestDao1 testDao1() {
		testDao();
		return new TestDao1();
	}
}
public class TestDao1 {
	public TestDao1(){
		System.out.println("testDao1");
	}
}

不加@Configuration的列印結果

加上@Configuration的列印結果

二、分析

從表面來看,當我們不加@Configuration註解的時候,我們的TestDao會被範例化兩次,這違背了我們spring預設單例的設計原則,當加上我們的@Configuration註解的時候,TestDao只被範例化了一次。

那麼其底層到底做了什麼,讓我們來深追一下spring原始碼吧。

當我們解析beanAppcofig的時候,會給它的一個屬性標識為Full,表明它是一個全註解類。

然後在我們呼叫ConfigurationClassPostProcessor.postProcessBeanFactory()方法的時候會去判斷我們的bean工廠當中是否有bean需要進行cglib代理。

然後遍歷configBeanDefs這個map

cglib代理主要是對我們的方法進行攔截增強;當我們執行AppConfig中的方法的時候會去執行cglib代理類中的代理方法,主要就是callBacks中的方法。

isCurrentlyInvokedFactoryMethod(beanMethod)) 

會判斷我們的執行方法和我們的呼叫方法是否是同一個;如果是同一個就呼叫父類別的方法進行new;如果不是就呼叫$$beanFactory.getBean()獲取。

三、總結

加上@Configuration註解主要是給我們的類加上了cglib代理。

在執行我們的設定類的方法時,會執行cglib代理類中的方法,其中有一個非常重要的判斷,當我們的執行方法和我們的呼叫方法是同一個方法時,會執行父類別的方法new(cglib代理基於繼承);當執行方法和呼叫方法不是同一個方法時會呼叫beanFactory.getBean獲取。


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