@Configuration parameter proxyBeanMethods in Spring Framework

insert image description here

1. Concept Analysis

In the Spring framework, the @Configuration annotation is used to declare a Java class as a configuration class, which replaces the traditional XML configuration method. Classes marked with the @Configuration annotation can contain the @Bean annotation to define Bean objects in the Spring container. In the @Configuration annotation, there is a very important attribute proxyBeanMethods, which controls the proxy behavior of the @Bean method in the @Configuration class. Let's go into very detail about this property:

  1. @Configuration annotation:

    • @Configuration is a meta-annotation provided by the Spring framework to indicate that a class is a configuration class.
    • Configuration classes usually contain the @Bean annotation, which defines methods for creating and configuring beans.
    • Spring scans the @Configuration class and registers the @Bean method in it as a Bean in the Spring container.
  2. @Bean annotation:

    • @Bean is an annotation used to define Spring Bean.
    • In the @Configuration class, the method marked by the @Bean annotation returns an object that will be registered in the Spring container as a Bean.
    • By default, the Spring container will use the method name as the name of the bean, and the name of the bean can also be specified through the name attribute of @Bean.
  3. proxyBeanMethods attribute:

    • proxyBeanMethods is an attribute of the @Configuration annotation, which is used to control the proxy behavior of the @Bean method.
    • In Spring 5 and earlier versions, the default value is true. Starting from Spring 5, the default value is true.
    • This property accepts a boolean value, set to true to enable proxy mode, set to false to disable proxy mode.
  4. Proxy Mode:

    • In the @Configuration class, when the proxyBeanMethods attribute is set to true, Spring will perform CGLIB proxy on the @Configuration class.
    • CGLIB is a powerful third-party library for generating subclasses of Java classes at runtime.
    • After the @Configuration class is proxied, when the @Bean method is called, Spring will check whether the Bean already exists. If it exists, it will directly return the existing Bean. Otherwise, the method will be called to create a new Bean and cache it.
    • The advantage of this is that when there are mutual calls between multiple @Bean methods, it can be guaranteed that calls to the same Bean will not be executed repeatedly, which improves the performance of the application.
  5. Disable proxy mode:

    • CGLIB proxying is disabled when the proxyBeanMethods property is set to false.
    • In the disabled proxy mode, the Spring container will execute the method body once every time the @Bean method is called, and the Bean object will not be cached.
    • The advantage of this is that every time the @Bean method is called, a new Bean object will be recreated, which is suitable for those scenarios that need to return a new instance each time.
  6. How to choose a proxy mode:

    • Choosing whether to enable proxy mode depends on the needs of the application.
    • If the @Bean methods in the @Configuration class do not call each other, and the creation of the Bean does not involve complex logic, you can consider enabling the proxy mode to improve performance.
    • If there are mutual calls between @Bean methods, or the creation logic of the Bean is more complicated, in order to ensure that each call returns a new instance, the proxy mode can be disabled.

Sample code:

@Configuration
public class MyConfiguration {
    
    

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

    @Bean
    public AnotherBean anotherBean() {
    
    
        return new AnotherBean(myBean()); 
    }
}

Summary:
The @Configuration annotation is used to declare the configuration class, and the @Bean annotation is used to define the Bean object in the Spring container. The proxyBeanMethods attribute controls the proxy behavior of @Bean methods. Enabling the proxy mode can improve performance, and disabling the proxy mode can ensure that a new instance is returned every time the @Bean method is called. Choosing whether to enable proxy mode depends on the needs of the application.
##2. Scene reproduction
In order to better understand the different usage scenarios of proxyBeanMethods, we create a simple example to demonstrate their effects. We will create a Spring application with a @Configuration class that defines two @Bean methods and test the behavior of proxyBeanMethods in different scenarios.

Scenario 1: Enable proxy mode

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = true)
public class ProxyEnabledConfiguration {
    
    

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

    @Bean
    public AnotherBean anotherBean() {
    
    
     //开启代理,实例Bean会被缓存,直接返回已存在的Bean
        return new AnotherBean(myBean()); 
    }
}

Scenario 2: Disable Proxy Mode

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class ProxyDisabledConfiguration {
    
    

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

    @Bean
    public AnotherBean anotherBean() {
    
    
    //禁用代理,每次都会生成新的实例Bean
        return new AnotherBean(myBean()); 
    }
}

MyBean.java:

public class MyBean {
    
    
    private static int instanceCounter = 0;
    private int instanceNumber;

    public MyBean() {
    
    
        instanceNumber = ++instanceCounter;
        System.out.println("Creating MyBean instance: " + instanceNumber);
    }

    public int getInstanceNumber() {
    
    
        return instanceNumber;
    }
}

AnotherBean.java:

public class AnotherBean {
    
    
    private MyBean myBean;

    public AnotherBean(MyBean myBean) {
    
    
        this.myBean = myBean;
        System.out.println("Creating AnotherBean instance using MyBean with instance number: " + myBean.getInstanceNumber());
    }
}

Test class:

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class App {
    
    

    public static void main(String[] args) {
    
    
        // proxyBeanMethods enabled
        AnnotationConfigApplicationContext context1 = new AnnotationConfigApplicationContext(ProxyEnabledConfiguration.class);
        AnotherBean anotherBean1 = context1.getBean(AnotherBean.class);

        // proxyBeanMethods disabled
        AnnotationConfigApplicationContext context2 = new AnnotationConfigApplicationContext(ProxyDisabledConfiguration.class);
        AnotherBean anotherBean2 = context2.getBean(AnotherBean.class);
    }
}

In the scenario where the proxy mode is enabled (ProxyEnabledConfiguration), MyBean will only be instantiated once, because AnotherBean will reuse the created MyBean instance, as can be seen from the console output:

Creating MyBean instance: 1
Creating AnotherBean instance using MyBean with instance number: 1

In the scenario where the proxy mode is disabled (ProxyDisabledConfiguration), MyBean will be instantiated once every time it is called, because there is no cache, you can see from the console output:

Creating MyBean instance: 1
Creating MyBean instance: 2
Creating AnotherBean instance using MyBean with instance number: 1
Creating MyBean instance: 3
Creating AnotherBean instance using MyBean with instance number: 2

By comparing these two scenarios, we can clearly see the impact of the proxyBeanMethods attribute.

Conceptual things are really confusing. Sometimes we want to explore the underlying principles, but we often hit a wall. However, we can’t give up. Read it several times, check the information, be compatible with the strengths of all families, take it down, absorb it, and understand it thoroughly , slowly, step by step, don't worry! ! !

Guess you like

Origin blog.csdn.net/weixin_53742691/article/details/132051388