Spring中@Component和@Configuration的區別

PHP定製開發發表於2022-10-09

正文

首先我們都知道使用Spring的@ComponentScan註解可以掃描到@Configuration和@Component的類,並將其交由Spring容器管理,預設會放入單例池中。
新建了一個BeanConfig類用來測試結果:

@Configuration
public class BeanConfig {}複製程式碼

透過上下文獲取IOC容器中的BeanConfig,發現確實是被CGLIB進行了代理。
在這裡插入圖片描述

執行檢視上下文中beanFactory的單例池中確實存在。
在這裡插入圖片描述

將BeanConfig類的@Configuration註解改為@Component後再看一下則顯示沒有被CGLIB代理。
在這裡插入圖片描述

問題

那麼Spring為什麼設計@Configuration註解修飾的Bean要被動態代理?

先說結果:Spring的目的是讓@Configuration註解的類中被@Bean註解的方法生成的物件是單例,那如何使一個方法每次生成返回的物件都是同一個,代理就是其中一種方式。
首先@Configuration註解的作用是用於定義配置類來替換XML配置檔案,被註解的類內部包含有一個或多個被@Bean註解的方法,這些方法會被用於構建BeanDefinition,初始化Spring容器。
也就是說@Configuration的主要目的是搭配@Bean註解替代XML配置檔案來向Spring容器注入Bean。
我們在BeanConfig類中增加兩個@Bean註解的方法:

@Configuration
public class BeanConfig {
    //@Scope("prototype")
    @Bean
    public Role role(){
        return new Role();
    }
    @Bean
    public User user(){
        Role r1=role();
        Role r2=role();
        System.out.println(r1==r2);
        return new User();
    }}複製程式碼

透過Spring的處理,直接呼叫 @Configuration 註解中bean 方法,獲取的就是同一個物件,這樣想要直接使用某個@Bean註解的物件就不需要 @Autowired 注入了。
當然你非要在方法上加上註解@Scope(“prototype”),每次呼叫該方法還是會生成不同的物件。

原始碼

註解配置讀取器:向BeanDefinitionMap中新增了7個元素,其中一個就是ConfigurationClassPostProcessor

org.springframework.context.annotation.AnnotationConfigApplicationContext#AnnotationConfigApplicationContext()

執行所有的BeanFactoryPostProcessor的postProcessorBeanFactory()方法

org.springframework.context.support.AbstractApplicationContext#refresh() 方法中的invokeBeanFactoryPostProcessors(beanFactory)org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanFactory

查詢到所有帶有 @Configuration 註解的 bean 定義,然後在第二個 for 迴圈中對類進行增強

org.springframework.context.annotation.ConfigurationClassPostProcessor#enhanceConfigurationClasses

總結

加了@Configuration的類會被CGLIB進行動態代理,不加或者加@Component註解則不會被代理。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70021881/viewspace-2917421/,如需轉載,請註明出處,否則將追究法律責任。

相關文章