@Configuration annotation and @bean annotation in SpringBoot configuration class

1.@Configuration annotation

Usage:
Act on the class. Role: Tell SpringBoot that this is a configuration class, which is equivalent to the xml configuration file in Spring.

@Configuration //告诉SpringBoot这是一个配置类 == 配置文件
public class Config {
    
    
}

2.@bean annotation

Usage: The @Bean annotation is used in the configuration class to register components to the IoC container on the method. By default, it is also a single instance.
Role: Adding components to the container is equivalent to the <bean> tag in the xml configuration file in Spring.
Understanding: Use the method name as the id of the component. The return type is the component type. The returned value is the instance of the component in the container

@Configuration //告诉SpringBoot这是一个配置类 == 配置文件
public class Config {
    
    

    @Bean   //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例
    public Person person1(){
    
    
        return new Person("Mr.Yu",21,"male");
    }

    @Bean("customize")  //id值也可以指定
    public Person person2(){
    
    
        return new Person("小明",20,"male");
    }
}

Print out the objects in our IoC container in the main program class to see if our person1 and customize are added to the container

@SpringBootApplication
public class MainApplication {
    
    
    public static void main(String[] args) {
    
    
        //1.返回我们IOC容器
        ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);

        //2.查看容器里面的组件
        String[] names = run.getBeanDefinitionNames();
        for (String name : names) {
    
    
            System.out.println(name);
        }
    }
}

Output result:
Insert picture description here
You can see that there are two objects we stored in the IoC container in the output result

3. Single instance

The instance stored in the IoC container with the @Bean annotation is also a single instance

public static void main(String[] args) {
    
    
        //1.返回我们IOC容器
        ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);

        //2.查看容器里面的组件
        String[] names = run.getBeanDefinitionNames();
        for (String name : names) {
    
    
            System.out.println(name);
        }

        //单实例
        Person person1 = run.getBean("person1",Person.class);
        Person person2 = run.getBean("person1",Person.class);
        System.out.println("person1 == person2 :"+ (person1 == person2));
}

Output result:
Insert picture description here

4. The configuration class is also a component of the container

@SpringBootApplication
public class MainApplication {
    
    
    public static void main(String[] args) {
    
    
        //1.返回我们IOC容器
        ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);

        //2.查看容器里面的组件
        String[] names = run.getBeanDefinitionNames();
        for (String name : names) {
    
    
            System.out.println(name);
        }
        
        //配置类本身也是组件
        Config bean = run.getBean(Config.class);
        //com.ysw.boot.config.Config$$EnhancerBySpringCGLIB$$4aa44992@381d7219
        System.out.println(bean);


    }
}

Output result:

com.ysw.boot.config.Config$$EnhancerBySpringCGLIB$$4aa44992@381d7219

5. Directly call the person1() method in the configuration class

What happens if we directly call the person1() method in the configuration class, whether it is taken from the IoC container or directly new an object?

  1. In the case of a configuration class of new, call the person1 method, which returns the object of new
  2. But if we get the configuration class from the container, no matter how many times the person1 method is removed, it will always return the same single-instance object, which is the object taken from the IoC container.
@SpringBootApplication
public class MainApplication {
    
    
    public static void main(String[] args) {
    
    
        //1.返回我们IOC容器
        ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);

        //2.查看容器里面的组件
        String[] names = run.getBeanDefinitionNames();
        for (String name : names) {
    
    
            System.out.println(name);
        }

        //配置类本身也是组件
        Config bean = run.getBean(Config.class);
        //获取到的本身就是代理对象
        //com.ysw.boot.config.Config$$EnhancerBySpringCGLIB$$4aa44992@381d7219
        System.out.println(bean);

        //如果我们直接调用person1方法,它是从IoC容器中拿还是直接new一个对象呢,
        //在new一个配置类出来的情况下,调用person1方法,它返回的是new出来的对象
        Config config = new Config();
        Person person3 = config.person1();
        Person person4 = config.person1();
        System.out.println("person3 == person4 :"+ (person3 == person4));

        //但是如果我们从容器中取得的配置类,无论再去掉用多少次person1方法,它始终返回的都是同一个单实例对象,也就是从IoC容器中拿的对象。
        //如果@Configuration(proxyBeanMethods = true)代理对象调用方法。SpringBoot总会检查这个组件是否在容器中有;
        //保持组件单实例
        Person person5 = bean.person1();
        Person person6 = bean.person1();
        System.out.println("person5 == person6 :"+ (person5 == person6));

    }
}

Output result:

Insert picture description here

6.proxyBeanMethods-proxy bean methods

The output result of the configuration object obtained from the container:

com.ysw.boot.config.Config$$EnhancerBySpringCGLIB$$4aa44992@381d7219

In the above output result, we can see that the configuration class object obtained from the container is itself a proxy object enhanced by SpringCGLIB

  • @Configuration() defaults to proxyBeanMethods = true.
  • If @Configuration(proxyBeanMethods = true), the proxy object calls the method. SpringBoot will always check whether this component already exists in the container, and when calling the method in the configuration class, it will return the component already in the container (that is, the object that already exists in the IoC container).
  • If @Configuration(proxyBeanMethods = false), it is not a proxy object calling method. SpringBoot will not check whether this component is already in the container, and a new object will be returned when the method in the configuration class is called.

@Configuration(proxyBeanMethods = false) Example: Change
the @Configuration() in 5 above to @Configuration(proxyBeanMethods = false). The
output result is:
Insert picture description here
Summary:

  • Full mode (proxyBeanMethods = true): to ensure that each @Bean method is called how many times the returned component is a single instance
  • Lite mode (proxyBeanMethods = false): How many times each @Bean method is called, the returned components are newly created
  • Component dependencies must use the Full mode default. Whether other default Lite mode
  • There is no dependency between configuration class components. Lite mode is used to speed up the container startup process. When the method in the configuration class is called, SpringBoot will not judge whether the object already exists in the container every time, reducing the judgment process
  • There is a dependency relationship between configuration class components. When calling a method in a configuration class, SpringBoot will determine whether the object already exists in the container every time, and the method will be called to get the previous single-instance component, using Full mode

Guess you like

Origin blog.csdn.net/MrYushiwen/article/details/111880916