最近看Nacos的源码,发现很多Configuration配置类上  @Configuration(proxyBeanMethods = false)   都把proxyBeanMethods设置成了false了。特地研究下。

 

 源码中默认是true,对这个属性的解释也可以大概知道。

1: 如果为true, 则表示被@Bean标识的方法都会被CGLIB进行代理,而且会走bean的生命周期中的一些行为(比如:@PostConstruct,@Destroy等 spring中提供的生命周期), 如果bean是单例的,那么在同一个configuration中调用

    @Bean标识的方法,无论调用几次得到的都是同一个bean,就是说这个bean只初始化一次。

2:  如果为false,则标识被@Bean标识的方法,不会被拦截进行CGLIB代理,也就不会走bean的生命周期中的一些行为(比如:@PostConstruct,@Destroy等 spring中提供的生命周期),如果同一个configuration中调用@Bean标识的方法,就只是普通方法的执行而已,并不会从容器中获取对象。所以如果单独调用@Bean标识的方法就是普通的方法调用,而且不走bean的生命周期。

所以,如果配置类中的@Bean标识的方法之间不存在依赖调用的话,可以设置为false,可以避免拦截方法进行代理操作,也是提升性能的一种优化。但是需要注意,@Bean标识的返回值对象还是会放入到容器中的,从容器中获取bean还是可以是单例的,会走生命周期。

看下面的例子:

public class MyBean {
    @PostConstruct
    public void init(){
        System.out.println("MyBean初始化了");
    }
    public void hello(){
        System.out.println("Mybean  hello");
    }
}
public class YourBean {

    public MyBean myBean;

    public YourBean(MyBean myBean){
         this.myBean=myBean;
    }

    @PostConstruct
    public void init(){
        System.out.println("YourBean 初始化了");
    }

    public void hello(){
        System.out.println("YourBean hello");
    }
}

 

@Configuration(proxyBeanMethods=true)

@Configuration(proxyBeanMethods = true)
public class ConfigureTest {
    @Bean
    public OrderEntity getOrderEntity(){
        return new OrderEntity();
    }

    @Bean
    public MyBean myBean(){
        return new MyBean();
    }

    @Bean
    public YourBean yourBean(){
       return new YourBean(myBean());
    }
}

 

测试方法:

@Component
public class InitClass implements InitializingBean , ApplicationContextAware {

    ApplicationContext applicationContext;

    @Override
    public void afterPropertiesSet() throws Exception {
        YourBean bean = this.applicationContext.getBean(YourBean.class); // 第一行
        YourBean bean1 = this.applicationContext.getBean(YourBean.class);  // 第二行
        MyBean myBean = this.applicationContext.getBean(MyBean.class);    // 第三行
        myBean.hello();
        bean.hello();
        bean1.hello();
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext=applicationContext;
    }
}

 

第一行执行完:MyBean和YourBean都进行初始化了,说明在new YourBean(myBean())中myBean()走了bean的生命周期,说明被CGLIB进行代理了。

 

 第二,三行执行完,没什么内容输出,说明YourBean,MyBean都初始化一次。

 


 

@Configuration(proxyBeanMethods=false)

@Configuration(proxyBeanMethods = false)
public class ConfigureTest {
    @Bean
    public OrderEntity getOrderEntity(){
        return new OrderEntity();
    }

    @Bean
    public MyBean myBean(){
        return new MyBean();
    }

    @Bean
    public YourBean yourBean(){
       return new YourBean(myBean());
    }
}

 

执行完第一行,只有YourBean初始化有输出:看到里面的MyBean属性是@5351

 

 执行完第二行,没有内容输出,bean1中的MyBean属性也是@5351

 

 第三行执行完,MyBean的初始化才输出,而且从容器中得到的这个bean是@5360

看到这里应该能体会到,proxyBeanMethods的含义了吧。为false的时候,@Bean标识的方法调用就是普通的方法调用,不会被代理。