最近看源碼時,經常看了下@Configuration(proxyBeanMethods = false)這樣的配置,但從命名上看應該是與代理有關的,于是抽個時間了解了下
首先這個是@Configuration注解中的一個參數,我們都知道,@Configuration是Spring中的配置類,一般用來申明Bean,在默認情況下proxyBeanMethods為true
從源碼中可以看到對該參數的描述如下:
Specify whether @Bean methods should get proxied in order to enforce bean lifecycle behavior, e.g. to return shared singleton bean instances even in case of direct @Bean method calls in user code. This feature requires method interception, implemented through a runtime-generated CGLIB subclass which comes with limitations such as the configuration class and its methods not being allowed to declare final.The default is true, allowing for 'inter-bean references' via direct method calls within the configuration class as well as for external calls to this configuration's @Bean methods, e.g. from another configuration class. If this is not needed since each of this particular configuration's @Bean methods is self-contained and designed as a plain factory method for container use, switch this flag to false in order to avoid CGLIB subclass processing.Turning off bean method interception effectively processes @Bean methods individually like when declared on non-@Configuration classes, a.k.a. "@Bean Lite Mode" (see @Bean's javadoc). It is therefore behaviorally equivalent to removing the @Configuration stereotype.
當直接在Configuration中直接通過方法,實現實例件的屬性依賴時,IDEA會有這樣一段提示:
Method annotated with @Bean is called directly in a @Configuration where proxyBeanMethods set to false. Set proxyBeanMethods to true or use dependency injection.
先通過下面的示例看下現象:
兩個配置類,寫法差不多,區別在與proxyBeanMethods的配置以及AnimalCage屬性的注入方法。
@Configuration(proxyBeanMethods = false)public class GenericConfiguration { @Bean public DogCage dogCage(){ return new DogCage(); } @Bean public AnimalCage animalEden(){ AnimalCage animalCage = new AnimalCage(); animalCage.addCage(dogCage()); return animalCage; }}@Configuration(proxyBeanMethods = true)public class ProxyConfiguration { @Bean public DogCage dogCage(){ return new DogCage(); } @Bean public AnimalCage animalEden(@Autowired List<Cage> cages){ return new AnimalCage(cages); }}
先看下GenericConfiguration配置的情況:
public class Tests { @Autowired private BeanFactory beanFactory; @Autowired private GenericConfiguration genericConfiguration; @Autowired private AnimalCage animalCage; @Autowired private DogCage dogCage; @Test public void runConfig() { log.info("configuration: {}", genericConfiguration); // 原始對象類型 log.info("Configuration中的Bean: {}", genericConfiguration.dogCage() == genericConfiguration.dogCage()); // 兩次結果不一樣 log.info("容器中的Bnea: {}", beanFactory.getBean(DogCage.class) == beanFactory.getBean(DogCage.class));// 從Spring容器中取值都是一樣的 animalCage.cages.forEach(cage -> { if (cage instanceof DogCage) { log.info("dogCage : {} ", cage == dogCage); // 和上面的對象不一致,非單例 } }); }}
再看下ProxyConfiguration配置的情況:
public class Tests { @Test public void runConfig() { log.info("configuration: {}", proxyConfiguration); // 1、CGLIB代理的對象 log.info("Configuration中的Bean: {}", proxyConfiguration.dogCage() == proxyConfiguration.dogCage()); // 2、兩次結果相同 log.info("容器中的Bnea: {}", beanFactory.getBean(DogCage.class) == beanFactory.getBean(DogCage.class));// 3、從Spring容器中取值都是一樣的 animalCage.cages.forEach(cage -> { if (cage instanceof DogCage) { log.info("dogCage : {} ", cage == dogCage); // 和上面的對象不一致,非單例 } }); }}
會得到這樣的現象:
看到上面的現象后,我們有必要了解下Spring配置中的Lite和Full兩種模式
lite模式包含:
full模式包含:
full模式使用特性:
lite模式使用特性:
@Configuration(proxyBeanMethods = false)的配置其實是Lite模式,這種模式下,配置類不會生成代理類,速度會更快,但是要注意,在配置類中的@Bean方法,不能用來實現單例級別的依賴。
本文鏈接:http://www.tebozhan.com/showinfo-26-14814-0.htmlConfiguration源碼,你了解多少?
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com