Configuration最近看源码时,经常看了下@Configuration(proxyBeanMethods = false)这样的配置,但从命名上看应该是与代理有关的,于是抽个时间了解了下
proxyBeanMethods首先这个是@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.
- 该属性的作用是指定标注了@Bean的方法在执行生命周期的时候是否应该被代理 。比如在代码中直接调用@Bean标注的方法时要返回共享的单例Bean实例(关闭代理之后不会返回共享的Bean实例) 。
- 该特性是通过运行时CGLIB子类 实现的方法拦截 。该子类有一些限制,比如配置类和它的方法不允许声明为final类型 。
- 默认为true,即允许 “inter-bean references” 通过配置类内部的直接方法调用 , 也可以通过外部调用该配置类的@Bean标注的方法 。如果该配置类是一个特殊的配置类:每一个@Bean标注的方法 都是自包含的 , 并设计为供容器使用的普通工厂方法,可以设置该属性为false,以避免CGLIB子类处理 。
- 关闭Bean方法拦截可以高效的单独处理@Bean方法,就像声明在一个non-@Configuration类上一样 , @Bean Lite Mode 。这种行为类似于删除@Configuration原型 。
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); // 和上面的对象不一致 , 非单例 } }); }}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 让你起飞的五个Prompt框架模型
- 苹果QQ聊天记录导出的3个方法你知道吗?
- 语音通话也能录音?你可能不知道
- 如何给微信上锁?教你三种方法,保护微信资金安全
- 一个简单的动作,比散步还简单!每天10分钟,帮你减肥缓解颈椎病
- 工作忙碌也能搬的搬砖游戏,这几款你一定爱!
- 黄碧云经典语录,我爱你似鲸入海似鸟投林
- 40岁之后,提升气质的12个小习惯,快来看,你占了几个?
- 搞笑有趣,越看越开心,每天好心情
- 被禁的6部高质量网剧,你有幸看过几部?