@Configuration屬性proxyBeanMethods詳解


@Configuration注釋中的proxyBeanMethods參數是springboot1.0,升級到springboot2.0之后新增的比較重要的內容,該參數是用來代理bean的。

理論
首先引出兩個概念:Full 全模式,Lite 輕量級模式

Full(proxyBeanMethods = true) :proxyBeanMethods參數設置為true時即為:Full 全模式。 該模式下注入容器中的同一個組件無論被取出多少次都是同一個bean實例,即單實例對象,在該模式下SpringBoot每次啟動都會判斷檢查容器中是否存在該組件
Lite(proxyBeanMethods = false) :proxyBeanMethods參數設置為false時即為:Lite 輕量級模式。該模式下注入容器中的同一個組件無論被取出多少次都是不同的bean實例,即多實例對象,在該模式下SpringBoot每次啟動會跳過檢查容器中是否存在該組件
什么時候用Full全模式,什么時候用Lite輕量級模式?
當在你的同一個Configuration配置類中,注入到容器中的bean實例之間有依賴關系時,建議使用Full全模式
當在你的同一個Configuration配置類中,注入到容器中的bean實例之間沒有依賴關系時,建議使用Lite輕量級模式,以提高springboot的啟動速度和性能

proxyBeanMethods 屬性默認值是 true, 也就是說該配置類會被代理(CGLIB),在同一個配置文件中調用其它被 @Bean 注解標注的方法獲取對象時會直接從 IOC 容器之中獲取;

看下源碼注解
/**
* Specify whether {@code @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 {@code @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 {@code final}.
*

The default is {@code true}, allowing for 'inter-bean references' via direct
* method calls within the configuration class as well as for external calls to
* this configuration's {@code @Bean} methods, e.g. from another configuration class.
* If this is not needed since each of this particular configuration's {@code @Bean}
* methods is self-contained and designed as a plain factory method for container use,
* switch this flag to {@code false} in order to avoid CGLIB subclass processing.
*

Turning off bean method interception effectively processes {@code @Bean}
* methods individually like when declared on non-{@code @Configuration} classes,
* a.k.a. "@Bean Lite Mode" (see {@link Bean @Bean's javadoc}). It is therefore
* behaviorally equivalent to removing the {@code @Configuration} stereotype.
* @since 5.2
*/
boolean proxyBeanMethods() default true;

注解的意思是 proxyBeanMethods 配置類是用來指定 @Bean 注解標注的方法是否使用代理,默認是 true 使用代理,直接從 IOC 容器之中取得對象;如果設置為 false, 也就是不使用注解,每次調用 @Bean 標注的方法獲取到的對象和 IOC 容器中的都不一樣,是一個新的對象,所以我們可以將此屬性設置為 false 來提高性能;

根據注釋 proxyBeanMethods 是為了讓使用 @Bean 注解的方法被代理而實現 bean 的生命周期的行為。

設置為 true,那么直接調用方法獲取 bean,不會創建新的 bean,而是會走 bean 的生命周期的行為。
設置為 false, 那么直接調用方法獲取 bean,會創建新的 bean,且不會走 bean 的生命周期的行為。
Configuration 源碼
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
@AliasFor(annotation = Component.class)
String value() default "";
boolean proxyBeanMethods() default true;

}

測試驗證代碼
測試代碼
public class AnnotationConfigApplicationContextTest {
@Test
public void refresh(){
AnnotationConfigApplicationContext ctx=new AnnotationConfigApplicationContext();
ctx.register(AppConfig.class);
ctx.refresh();
MyBean myBean=ctx.getBean(MyBean.class);
myBean.sayHello();
YourBean yourBean=ctx.getBean(YourBean.class);
yourBean.sayHello();
}
}

Configuration 代碼,設置為 false
@Configuration(proxyBeanMethods = false)
public class AppConfig {
@Bean
public MyBean myBean(){
return new MyBean();
}
@Bean
public YourBean yourBean(){
return new YourBean(myBean());
}
}

Mybean 代碼
public class MyBean {
public MyBean(){
System.out.println("MyBean construct......");
}
@PostConstruct
public void init(){
System.out.println("MyBean PostConstruct ....");
}
public void sayHello(){
System.out.println("Hi MyBean ,hello world!");
}
}

YourBean 代碼
public class YourBean {
public MyBean myBean;

public YourBean(MyBean myBean){
System.out.println("YourBean construct...");
this.myBean=myBean;
}
@PostConstruct
public void init(){
System.out.println("YourBean PostConstruct...");
}
public void sayHello(){
System.out.println("Hi YourBean ,hello world!");
}
}

執行 refresh 測試測試代碼結果(proxyBeanMethods = false)
MyBean construct...... 打印了兩次,說明被 new 了兩次

10:04:56.066 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'myBean'
MyBean construct......
MyBean PostConstruct ....
10:04:56.069 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'yourBean'
MyBean construct......
YourBean construct...
YourBean PostConstruct...
Hi MyBean ,hello world!
Hi YourBean ,hello world!

執行 refresh 測試測試代碼結果(proxyBeanMethods = true)
MyBean construct...... 只打印了一次,說明只被 new 了一次。

10:06:51.727 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'myBean'
MyBean construct......
MyBean PostConstruct ....
10:06:51.741 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'yourBean'
YourBean construct...
YourBean PostConstruct...
Hi MyBean ,hello world!
Hi YourBean ,hello world!

轉:https://www.1024sou.com/article/561144.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM